android6.0 mediaserver内存分配失败问题

转载自我的CSDN Blog

有客户反馈视频播放一段时间就卡住了,且是必现。从logcat信息上发现是mediaserver进程异常崩溃了,Log如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
ABI: 'arm'
pid: 246, tid: 1710, name: DecoderAudio >>> /system/bin/mediaserver <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
r0 00000000 r1 89c17780 r2 00001180 r3 00000000
r4 b79822a0 r5 00001200 r6 89c17704 r7 89c17740
r8 89c17738 r9 00000000 sl 03598a78 fp 00000000
ip b64234c8 sp 89c176f8 lr b63eaf75 pc b6a8794c cpsr 200f0010
d0 f099f6d8f041f6c2 d1 f108f776f10ef738
d2 f08af7eff0a6f79c d3 f0f3f71df0c6f7ef
d4 f171f601f106f624 d5 f366f728f260f699
d6 f5a8f7bff45ff779 d7 f676f741f6c2f7d2
d8 3ef5d867c3ece2a5 d9 412e848000000000
d10 0000000000000000 d11 0000000000000000
d12 0000000000000000 d13 0000000000000000
d14 0000000000000000 d15 0000000000000000
d16 0000000000000000 d17 0000000000000000
d18 3ff0000000000000 d19 4091780000000000
d20 be5ae5d13e0705cf d21 4037f9dcb5112287
d22 bf2a017308872714 d23 3de5d93a5acfd57c
d24 3ec71de357b1fe7d d25 3e21e0e0299e8cc5
d26 4037f9dcb5112287 d27 40032e4a2a741b9f
d28 3f895d470d6e9486 d29 3f895d470d6e9486
d30 3fe797c6a435ce85 d31 400921fb54400000
scr 68000012

backtrace:
#00 pc 0001694c /system/lib/libc.so (memcpy+112)
#01 pc 00042f71 /system/lib/librkffplayer.so (_ZN7android13RkAudioPlayer10queueAudioEPsix+56)
#02 pc 0004d509 /system/lib/librkffplayer.so (_ZN7android9FFMPlayer6decodeEPsixxiPv+652)
#03 pc 0003167f /system/lib/librkffplayer.so (_ZN12DecoderAudio17SoftDecodeProcessEP8AVPacket+910)
#04 pc 00030ea9 /system/lib/librkffplayer.so (_ZN12DecoderAudio6decodeEPv+280)
#05 pc 00034203 /system/lib/librkffplayer.so (_ZN12PlayerThread11startThreadEPv+46)
#06 pc 000417c7 /system/lib/libc.so (_ZL15__pthread_startPv+30)
#07 pc 00019313 /system/lib/libc.so (__start_thread+6)

在导致异常的代码附近添加LOG确认了是malloc调用返回空指针,内存分配失败了,但查看kmsg并未发现LMK或者OOM出现。

查看系统limit没有问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
root@rk3288:/ # ulimit -Sa
time(cpu-seconds) unlimited
file(blocks) unlimited
coredump(blocks) 0
data(KiB) unlimited
stack(KiB) 8192
lockedmem(KiB) 64
nofiles(descriptors) 1024
processes 10576
sigpending 10576
msgqueue(bytes) 819200
maxnice 40
maxrtprio 0
resident-set(KiB) unlimited
address-space(KiB) unlimited

root@rk3288:/ # ulimit -Ha
time(cpu-seconds) unlimited
file(blocks) unlimited
coredump(blocks) unlimited
data(KiB) unlimited
stack(KiB) unlimited
lockedmem(KiB) 64
nofiles(descriptors) 4096
processes 10576
sigpending 10576
msgqueue(bytes) 819200
maxnice 40
maxrtprio 0
resident-set(KiB) unlimited
address-space(KiB) unlimited

再看mediaserver进程,发现它的address-space被限制在1370941585 bytes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
130|root@rk3288:/ # cat /proc/4506/limits                                      
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 10576 10576 processes
Max open files 1024 4096 files
Max locked memory 65536 65536 bytes
Max address space 1370941585 unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 10576 10576 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 40 40
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us

通过命令修改进程的limit,重新测试视频正常:

1
prlimit 4506 9 -1 -1

google从Android6.0开始,对mediaserver进程的虚拟内存大小做出了限制,默认值是系统总内存的65%,这在普通的手机及平板等产品上没有问题,但在一些定制的产品,比如低内存的电视盒子,或者是多路视频同时播放的场景,这些产品在播放视频时候对内存的消耗在系统中占比可能超过65%,从而触发limit机制导致内存申请失败。