目的:总结linux进程内存泄漏导致crash的分析方法及解决过程
问题背景:插入usb设备并配置启动dlna功能,测试较长一段时间后会导致cpu和内存占用率很高以致开发板crash,有ps下的进程状态截图和crash日志
关键节点:
1.问题crash复现
2.在陌生的源码中寻找突破口
3.分析日志
4.分析主进程及子进程代码
分析过程:
节点1——
按照问题描述进行多次反复测试,问题并没有复现。观察提供的进程状态截图,按照截图中的状态启动对应进程(包括voice相关),尽量模拟同样的环境,继续测试,问题依然没有复现。开始怀疑跟usb设备中的文件系统、文件内容(包括图片格式类型,视频类型、音频类型)有关,于是在移动硬盘对应目录下copy大量的图片视频音频文件(达到60G左右,上十万个文件),测试1个小时左右出现crash,提示voice进程out of memory错误。
节点2——
源码文件那么多怎么找突破口,一般是从主进程入手。由于该功能启动时会用到一个重要参数,即对应的目录路径path,开始研究进程如何使用该参数,发现一个重要子进程scan,会迭代扫描path路径下所有的目录和文件并写入数据库db文件,文件越多扫描进程持续时间越长(可超过1个小时),top观察内存和cpu使用率占比很高,一段时间后即crash,由于内存耗尽导致voice需要大量申请内存失败最终crash。开始怀疑是迭代扫描导致大量内存未及时释放所致。
节点3——
观察日志代码发现进程会将日志保存在usb设备path目录下,于是仔细研究日志发现,每次都能正常扫描整个目录,且扫描结束后在做inotify过程中将crash,于是推断扫描进程没有泄漏问题,但其依然会耗掉大量内存。研究扫描进程之后的代码,又发现另一子进程inotify,主要实现媒体文件的同步操作,该进程会将扫描结果(上万条媒体记录)存入链表观测点进行观测。于是将扫描结束后的inotify相关代码注释掉继续调试,发现不再crash。尝试将inotify记录数减半,测试也不会crash,但是在播放器中随意点击播放会出现卡死现象,似乎还是没有解决根本问题。
节点4——
回到主进程整体分析,无论前面如何调试,内存总是消耗很大没有变好趋势,到底在什么地方会消耗很大内存呢?于是在主进程中去掉两个子进程,果然内存消耗很小。根据前面的调试,scan进程中没有内存泄漏,scan进程和inotify进程均采用pthread_create方式创建,scan扫描结束后进程也会结束,inotify进程则一直生存。上网查询发现pthread_create方式使用不当会导致大量内存泄漏,默认会消耗2-8M左右内存(可调整),根据网上众多的解决方法调整不起效果,不知缘何。于是想到可不可以将scan和inotify整合到一个进程中,或者采用fork方式来取代pthread_create方式调整scan进程,采用后一种方式调整测试,功能正常,不会crash和卡死现象,效果有改观,内存占用比降低明显,扫描结束后趋于稳定。