从启动脚本运行应用程序时 ALSA snd_pcm_hw_params_any 崩溃

Posted

技术标签:

【中文标题】从启动脚本运行应用程序时 ALSA snd_pcm_hw_params_any 崩溃【英文标题】:ALSA snd_pcm_hw_params_any crashed when run the application from startup script 【发布时间】:2021-02-14 17:39:18 【问题描述】:

我下载了 ALSA 示例源代码 (https://gist.github.com/ghedo/963382) 并在 putty 窗口下测试运行,它可以工作。然而,当放入带有或不带有“sudo”的启动脚本(例如rc.local)时,它崩溃了。

注意:应用程序只有在开机自动运行后才会崩溃;如果在putty(命令行)中运行脚本,没问题。

在每个 snd_xxx 函数调用之前添加日志记录后,发现应用程序在调用 snd_pcm_hw_params_any 后停止,这意味着它在 snd_pcm_open 和 snd_pcm_hw_params_alloca 之后崩溃。以下是代码:

    g_pLog->LogInfo(LOG_SYS, "[audio]snd_pcm_open"); /////logged 
    if ((pcm = snd_pcm_open(&pcm_handle, acDev, /////PCM_DEVICE, acDev="default:0"
                    SND_PCM_STREAM_PLAYBACK, 0)) < 0)
    
        sprintf(acLog, "[audio]Can't open \"%s\" PCM device. %s\n", acDev, snd_strerror(pcm));
        g_pLog->LogInfo(LOG_SYS, acLog);
        return -1;
    


    g_pLog->LogInfo(LOG_SYS, "[audio]snd_pcm_hw_params_alloca");  /////logged
    /* Allocate parameters object and fill it with default values*/
    snd_pcm_hw_params_alloca(&params);

    g_pLog->LogInfo(LOG_SYS, "[audio]snd_pcm_hw_params_any");  /////logged and is the last line
    snd_pcm_hw_params_any(pcm_handle, params);

    g_pLog->LogInfo(LOG_SYS, "[audio]snd_pcm_hw_params_set_access");
    /* Set parameters */
    if (pcm = snd_pcm_hw_params_set_access(pcm_handle, params,
                    SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
...

收集核心转储文件后使用gdb“bt full”查看,结果为:

root@linaro-ubuntu-desktop:/test# gdb ./AudioPlayer /opt/core.AudioPlayer.6277.1604311455.6
GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "arm-linux-gnueabi".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /test/AudioPlayer...(no debugging symbols found)...done.
[New LWP 6277]
[Thread debugging using libthread_db enabled]
Core was generated by `/test/AudioPlayer'.
Program terminated with signal 6, Aborted.
#0  0x2ad8bed6 in ?? () from /lib/arm-linux-gnueabi/libc.so.6
(gdb) bt full
#0  0x2ad8bed6 in ?? () from /lib/arm-linux-gnueabi/libc.so.6
No symbol table info available.
#1  0x2ad9a0da in raise () from /lib/arm-linux-gnueabi/libc.so.6
No symbol table info available.
#2  0x2ad9c506 in abort () from /lib/arm-linux-gnueabi/libc.so.6
No symbol table info available.
#3  0x2ad951ec in __assert_fail () from /lib/arm-linux-gnueabi/libc.so.6
No symbol table info available.
#4  0x2ac6cb72 in snd_pcm_hw_refine () from /usr/lib/arm-linux-gnueabi/libasound.so.2
No symbol table info available.
#5  0x0000aca8 in main ()
No symbol table info available.

注意“snd_pcm_hw_refine”不是直接从应用程序调用的。

我想知道在putty中运行和从开机启动脚本运行有什么区别,以及如何解决这个故障。如果您能提供建议,不胜感激......

【问题讨论】:

没有调试符号帮助不大。但是,从 rc.local 开始——确保 alsa 的所有先决条件都已启动并运行,然后再尝试启动它。此外,从 rc.local 运行它的用户可能没有通过 udev 或其他任何方式访问音频设备的权限(尽管 sudo 可以)。我唯一的想法是在Super User 或Unix & Linux 上与主题无关和更好 关于如何避免源代码级别的权限问题的任何想法?我尝试了以下但没有帮助:1.将 snd_xxx 调用延迟 30 秒(以确保驱动程序启动); 2.在调用第一个snd命令(snd_pcm_open)之前,读取“/proc/asound/cards”以确保卡准备好; 3. 使用从 rc.local 运行的另一个进程使用 system("sudo ....") 调用此应用程序 不,不是因为我不了解 alsa 或它的启动,而是因为我完全不知道您设备上的启动是什么。如果您仍在使用 rc.local - 这告诉我您的发行版仍在使用 init 文件,或者它具有 systemd 并且只是决定保留它在引导过程中(某处)挂钩的旧 rc.local 命名约定。此外,当您的 rc.local 在引导过程中被挂钩时,也会产生影响。实际启动一般为/path/to/alsactl restore。但是当它被调用时,所有/dev/snd/control* 设备必须已经设置好了。 您将在正确的 StackExchange 站点上获得更多答案。我投票结束这个问题,因为您的问题与“编程”无关,它更适合 StackExchange 站点 Super User 或 Unix & Linux。 (您也可以尝试AskUbuntu)您在其中一个网站上找到答案的可能性要高出 10 倍。 谢谢大卫,但是为什么这不是与编程相关的问题?不是每个应用程序(如这个)都可以自动加载吗?那么如何通过应用本身(源码层面)来解决呢? 【参考方案1】:

snd_pcm_open() open 的调用失败。然后错误代码检查失败,因为pcm 未签名。 snd_pcm_hw_params_any() 然后崩溃,因为 pcm_handle 为 NULL。

该代码中还有很多其他错误。忘掉它。使用这样的东西:

#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>

static void alsa_check(int result, const char *call)

    if (result < 0) 
        fprintf(stderr, "%s failed: %s\n", call, snd_strerror(result));
        exit(1);
    

#define CHECK(f) alsa_check(f, #f)

static void play(snd_pcm_t *pcm, int frame_size)

#define FRAMES 50000
    void *buf, *data;
    int frames, rest;

    buf = malloc(FRAMES * frame_size);
    for (;;) 
        frames = fread(buf, frame_size, FRAMES, stdin);
        if (frames <= 0)
            break;
        rest = frames;
        data = buf;
        while (rest > 0) 
            frames = snd_pcm_writei(pcm, data, rest);
            if (frames < 0)
                CHECK(snd_pcm_recover(pcm, frames, 0));
            else 
                rest -= frames;
                data += frames * frame_size;
            
        
    
    free(buf);


int main(int argc, char *argv[])

    const char *device = "default";
    snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
    snd_pcm_access_t access = SND_PCM_ACCESS_RW_INTERLEAVED;
    unsigned int channels, rate;
    unsigned int latency = 500000; /* 0.5 s */
    snd_pcm_t *pcm;

    if (argc != 3) 
        fprintf(stderr, "Usage: %s rate channels < inputfile\n", argv[0]);
        return 1;
    
    rate = atoi(argv[1]);
    channels = atoi(argv[2]);

    CHECK(snd_pcm_open(&pcm, device, SND_PCM_STREAM_PLAYBACK, 0));

    CHECK(snd_pcm_set_params(pcm, format, access, channels, rate, 1, latency));

    play(pcm, channels * snd_pcm_format_physical_width(format));

    CHECK(snd_pcm_drain(pcm));
    snd_pcm_close(pcm);
    return 0;

【讨论】:

谢谢 CL。有什么可供我尝试的替代建议吗? 这样的。 您好 CL,感谢您的源代码。我快速编译并测试它,但我只听到大约 1 秒并结束:./play 32000 1 &lt; /opt/test1.wav,没有错误打印出来。这个音频文件大概4.5s,运行aplay /opt/test1.wav,结果Playing WAVE '/opt/test1.wav' : Signed 16 bit Little Endian, Rate 32000 Hz, Mono,可以听到所有4.5s。 嗯,我认为不会发生短写。立即尝试。 您好 CL,使用带有 rest/data 的新更新,收到编译警告,`play.cc:33:34: 警告:在算术中使用的类型为 'void *' 的指针 [-Wpointer-算术]'。但是结果和之前一样,只听到1s左右

以上是关于从启动脚本运行应用程序时 ALSA snd_pcm_hw_params_any 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

使用 ALSA 从 Line IN 录制声音

调用 alsa-lib 后启动时出现错误的 VLC 卷

Ubuntu:系统启动服务

如何在不重新启动树莓派本身的情况下重新启动 ALSA?

从 C 代码中以 dB 为单位设置 ALSA 主音量

Cadence 未显示 ALSA 驱动程序选项卡