苍翼之刃:论File Descriptor泄漏如何导致Crash?

栏目: 编程工具 · 发布时间: 7年前

内容简介:苍翼之刃:论File Descriptor泄漏如何导致Crash?

本文来自于腾讯 Bugly,是由 Bugly 邀请腾讯内部各位技术大咖,通过日常工作经验的总结以及感悟撰写而成,内容均属原创,非经作者同意,请勿转载。

这一期的团队分享,我们特邀苍翼之刃的开发负责人Jay,为大家分享在Android项目中遇到的一些Crash。

苍翼之刃外文:BlazBlue Revolution Reburning,是由Arc Systerm Works 正式授权,并由 91Act 负责研发的横板动作手游,森利道全程监修,也是苍翼默示录系列唯一的一部横板动作手游。 游戏内部代号为:BBRR,全称是BLAZBLUE Revlution Reburning,续BBCT、BBCS、BBCS2、BBEX、BBCP 之后的又一力作。

背景

nix系统中,许多的资源都会被定义为File Descriptor(下面简称FD),例如普通文件、socket、std in/out/error等等。每个 nix系统中,单个进程可以使用的FD数量是有上限的。不同的*nix系统中,这个上限各有区别,例如在Android里面这个上限被限制为1024。

案例分析

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

看来是和OpenGL有关系,于是我们进一步对程序输出的log进行观察,又发现: 苍翼之刃:论File Descriptor泄漏如何导致Crash?

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

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

我们对我们已有的设备反复试验,确实了只有Adreno的设备(小米3,HTC M8,华为P7等)会在特定条件下出现这种奇奇怪怪的随机Crash。而其他设备例如小米Pad(Tegra),三星S3(Mali)等都不会出现这种问题。

这个问题确实头疼,在网上搜索了很久也没找到有用的信息。直到在某次小米3上再次测试的时候,发现了log里面还有一条必然出现的信息: 苍翼之刃:论File Descriptor泄漏如何导致Crash?

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

苍翼之刃:论File Descriptor泄漏如何导致Crash?

通过不停测试程序,发现已打开的文件数量一直有增无减,而当这些被打开的文件数量接近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;
  • 有的设备不会出现异常,但是会导致OpenGL停止工作(halt rendering),其表现结果就是程序卡住无响应;
  • 有的设备可能什么都不会发生,但是如果你的交互触发了其他逻辑:比如按回退键弹出对话框,对话框也需要FD,但是获得不到,那么弹出对话框的逻辑将抛出异常。 于是这就有了各种奇奇怪怪的Crash。

解决方案

通过对代码的排查,我们发现在使用SoundPool处理音效的时候,确实存在FD泄露的情况: 苍翼之刃:论File Descriptor泄漏如何导致Crash?

虽然我们在不需要这些音效的时候,对其进行了卸载处理,但不知道是SoundPool类自身的缺陷,还是我们的使用不当,在实际测试中我们发现unload过后,在load中通过openFd打开的FD并没有被释放掉。 强制调用System.gc()在一些设备(例如小米3)上可以释放掉这部分FD,但是另一些设备(例如HTC M8)即使强制gc这无法卸载掉它们,于是便出现了FD泄露的情况。 最终我们自行对这些FD进行管理,并且在unload的时候手动调用这些FD的close方法: 苍翼之刃:论File Descriptor泄漏如何导致Crash?

这之后FD再无泄露的情况发生,之前的各种设备上面的各种奇奇怪怪的Crash都被处理好了。

小结

这个问题粗略说起来就是:因为播放了太多的音效,导致Adreno底层渲染失败,以至于上层逻辑各种失措,产生了很多奇奇怪怪的Crash。 准确的解释应该是:程序中的FD泄露如同内存泄露一样是同样需要得到关注的问题,FD的耗尽如同内存的耗尽一样会导致程序的各种异常情况发生,但是前者不如后者那么知名也不如后者容易被察觉。

如果你觉得内容意犹未尽,如果你想了解更多相关信息,请扫描以下二维码,关注我们的公众账号,可以获取更多技术类干货,还有精彩活动与你分享~ 苍翼之刃:论File Descriptor泄漏如何导致Crash?

腾讯 Bugly是一款专为移动开发者打造的质量监控工具,帮助开发者快速,便捷的定位线上应用崩溃的情况以及解决方案。智能合并功能帮助开发同学把每天上报的数千条 Crash 根据根因合并分类,每日日报会列出影响用户数最多的崩溃,精准定位功能帮助开发同学定位到出问题的代码行,实时上报可以在发布后快速的了解应用的质量情况,适配最新的 iOS, Android 官方操作系统,鹅厂的工程师都在使用,快来加入我们吧!


以上所述就是小编给大家介绍的《苍翼之刃:论File Descriptor泄漏如何导致Crash?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

产品增长力

产品增长力

李阳 / 机械工业出版社 / 2018-4-1 / 59

本书由京东资深数据产品经理撰写,重新定义了数据与产品、业务的关系,从数据分析方法、数据价值挖掘、数据结果倒逼业务优化3个层次,以及设计、运营和优化3个维度,为产品增长提供了科学的依据和方法论,得到了PMCaff创始人阿德、GrowingIO创始人&CEO张溪梦、增长官研究院创始人范冰、腾讯高级产品经理刘涵宇等专家的高度评价。 全书内容以理论为主线,以实操为目标,萃取技术实操与管理思维中的精华......一起来看看 《产品增长力》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码