客户使用蓝牙a2dp source功能,连接蓝牙耳机播放音乐高概率出现播放无声的现象。
但在客户使用相同btmanager版本的其他机型上并没有遇到这个问题。
在出现播放无声问题时,btmanager会一直出现如下的打印:
BTMG[aw_pcm_open:400]: --->Couldn't open PCM:bluealsa:DEV=28:37:13:3B:DA:78
BTMG[_a2dp_src_pcm_write:150]: a2dp source open pcm error: Out of memory;
从log来看,播放时没有成功打开蓝牙虚拟声卡,所以播放没有声音是必然的。其中打开蓝牙声卡是使用标准函数snd_pcm_open,
而错误信息是 Out of memory。显然从日志来看,此问题与系统内存有关系。客户机器是512M内存。
既然与内存有关系,便从内存方向去分析此问题:
1)查看当前内存信息
cat /proc/meminfo
但是看内存信息,在声卡一直打不开的时候,MemFree也有 10M左右,所以就觉得有点奇怪了,为什么内存这么多,还是申请不到内存打开声卡呢?
难道是脏内存太多了?
2)尝试线程的栈调大
- 把btmanager里面相关的线程栈调高至20K,还是无效。
- 修改C库把默认线程的栈修改为1M,依然无效。
3)清理缓存
是不是脏内存太多,内存不连续?
使用echo 3 > /proc/sys/vm/drop_caches 清理一下,发现就可以正常申请了。
但是让内存的同事看了下连续内存还是足够的,所以这还不是根本原因。
4)跟踪代码
通过在alsa-lib 里面增加打印,最终发现是在snd_user_file函数里面调用wordexp(file, &we, WRDE_NOCMD);
返回了WRDE_NOSPACE,而打开的file /usr/share/alsa/alsa.conf也只有10K左右。再继续跟踪C库里面的wordexp函数,发现是在fork的时候有问题。
接着又做了个实验,同时在出问题的时候,我们在非打开声卡的地方调用fork函数,也是会申请不到内存。
所以本质上是fork函数导致的,打开声卡的过程刚好触发了这个问题。