设为首页 加入收藏

TOP

[转]File Descriptor泄漏导致Crash: Too many open files(一)
2017-10-13 10:04:12 】 浏览:6535
Tags:File Descriptor 泄漏 导致 Crash: Too many open files

在实际的Android开发过程中,我们遇到了一些奇奇怪怪的Crash,通过sigaction再配合libcorkscrew以及一些第三方的Crash Reporter都捕获不到发生Crash的具体信息,十分头疼。然后我们通过Bugly上报的Java的CallStack观察发现这些Crash发现了一些共同的信息:

看来是和OpenGL有关系,于是我们进一步对程序输出的log进行观察,又发现:

从这个log里面我们获得了几个信息:

  1. 几乎所有出现这种Crash的设备,都是Adreno的GPU
  2. 几乎所有Crash都会伴随着requestBuffer failed

我们对我们已有的设备反复试验,确实了只有Adreno的设备(小米3,HTC M8,华为P7等)会在特定条件下出现这种奇奇怪怪的随机Crash。而其他设备例如小米Pad(Tegra),三星S3(Mali)等都不会出现这种问题。这个问题确实头疼,在网上搜索了很久也没找到有用的信息。直到在某次小米3上再次测试的时候,发现了log里面还有一条必然出现的信息:

E/MemoryHeapBase(18703): error creating ashmem region: Too many open files

这个信息间接的指出了问题,也给了我们一些提示:似乎打开了过多的文件。于是靠着这个灵光,我们尝试着在程序中输出所有已打开的文件:

 SHOW FILE HANDLES:
 0 (socket:[285038]): read-write 1 (/dev/null): read-write 2 (/dev/null): read-write 3 (/dev/log/main): cloexec write-only 4 (/dev/log/radio): cloexec write-only 5 (/dev/log/events): cloexec write-only 6 (/dev/log/system): cloexec write-only 7 (/sys/kernel/debug/tracing/trace_marker): write-only 8 (/dev/__properties__): 9 (/dev/binder): cloexec read-write 10 (/dev/log/main): cloexec write-only 11 (/dev/log/radio): cloexec write-only 12 (/dev/log/events): cloexec write-only 13 (/dev/log/system): cloexec write-only 14 (/system/framework/framework-res.apk): 15 (/system/framework/core-libart.jar): 16 (pipe:[282578]): nonblock 17 (/dev/alarm): 18 (/dev/cpuctl/tasks): cloexec write-only 19 (/dev/cpuctl/bg_non_interactive/tasks): cloexec write-only 20 (socket:[282569]): read-write 21 (pipe:[282570]): 22 (pipe:[282570]): write-only 23 (pipe:[282578]): nonblock write-only 24 (anon_inode:[eventpoll]): read-write 25 (/data/app/---app_name---/base.apk): 26 (/data/data/---app_name---/databases/bugly_db): cloexec read-write 27 (socket:[285047]): read-write 28 (anon_inode:mali-8938): cloexec 29 (socket:[282605]): nonblock read-write 30 (socket:[283605]): nonblock read-write 31 (/dev/null): read-write 32 (/dev/ump): read-write 33 (socket:[285045]): nonblock read-write 34 (/dev/null): read-write 35 (/dev/mali): read-write 36 (anon_inode:mali-8938): cloexec 37 (anon_inode:mali-8938): cloexec 38 (/data/app/---app_name---/base.apk): 39 (anon_inode:mali-8938): cloexec 40 (anon_inode:mali-8938): cloexec 41 (/dev/null): read-write 42 (/dev/null): read-write 43 (/data/app/---app_name---/base.apk): 44 (/dev/null): read-write 45 (anon_inode:mali-8938): cloexec 46 (/data/data/---app_name---/files/DefaultFont.ttf): 47 (/data/app/---app_name---/base.apk): 48 (anon_inode:sync_fence): 49 (/dev/null): read-write 50 (socket:[285060]): cloexec read-write 52 (anon_inode:mali-8938): cloexec 53 (anon_inode:mali-8938): cloexec 54 (/dev/null): read-write 55 (anon_inode:sync_fence): 56 (pipe:[284134]): write-only 58 (anon_inode:sync_fence): 62 (anon_inode:sync_fence): 63 (anon_inode:sync_fence):

通过不停测试程序,发现已打开的文件数量一直有增无减,而当这些被打开的文件数量接近1024的时候,上面的eglSwapBuffers必然出错。于是乎我们得出一个中间结论:

  • 如果程序打开的文件数量过多,会导致OpenGL swap buffer失败!

这从字面上看着似乎有些扯淡,因为这两者总感觉没啥联系。这个问题只会出现在Adreno的GPU上面,于是我们猜想:

  • Adreno的驱动在swap buffer的时候,需要申请新的FD,这个FD可能是某些硬件IO,具体不得而知;
  • 如果程序中其他的各种FD使用过多接近上限,会导致Adreno的驱动申请不到必要的FD,因此导致swap buffer失败。

这样看起来似乎就比较有道理了。虽然sawp buffer本身是不会Crash的,他并没有raise任何signal,只是简单的返回了一个错误的结果,但这会导致上层逻辑出现异常。这些异常在不同的设备上表现不一样:

  • 有的设备会在Java层的eglSwapBuffers触发Java层的Exception导致Crash;
  • 有的设备不会出现异常,但是会导致OpenG
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Android 开发一定要看的15个实战.. 下一篇安卓四大组件之广播

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目