Android的BUG(二) - SurfaceTexture中的野指针
当初遇到这个bug,是不定期的低概率出现,最后找到一个比较容易重现的步骤:
启动系统
然后进google +
新建一个帐号(注意是新建一个帐号)
没几步就重启了
这个BUG,一开始追踪也是无头绪的,在这个bug出现时,系统的debuggerd还是有些问题,pt_regs设置的和内核对应不
上,tombstone的信息完全无用,core dump功能也是无法使用,唯一的线索就是一点点logcat的trace, trace如下:
D/OpenGLRenderer( 2021): Flushing caches (mode 1)
D/OpenGLRenderer( 2021): Flushing caches (mode 0)
D/OpenGLRenderer( 1986): Flushing caches (mode 1)
W/SurfaceTexture( 1451): freeAllBuffersLocked called but mQueue is not empty
D/OpenGLRenderer( 1986): Flushing caches (mode 0)
F/libc ( 1451): Fatal signal 11 (SIGSEGV) at 0x00000024 (code=1)
I/DEBUG ( 1449): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
I/DEBUG ( 1449): Build fingerprint: 'xxxx/IML74K/eng.freshui.20120213.154128:user/test-keys'
I/DEBUG ( 1449): pid: 1451, tid: 1455 >>> /system/bin/surfaceflinger <<<
I/DEBUG ( 1449): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000024
重现时的错误,基本上都是类似的trace。 从此入手开始查找。 Trace中的一句话:
W/SurfaceTexture( 1451): freeAllBuffersLocked called but mQueue is not empty
是最大的怀疑目标,基于捉虫的经验,先做假定,已经可以解释出错的原因和现象了:
- mQueue通常是被两个模块使用的,一个enqueue,一个dequeue
- 出错时,要将mQueue 给free掉,但mQueue不空,说明有人在用
- 如果不管这个警告,强行将mQueue给free掉,极有可能造成另外一个模块使用被free掉的内存而引起段错误
转回头看代码,SurfaceTexture.cpp, 查一下mQueue的使用地方,哪里有出现free buffer的时候,mQueue 不为空的可能? 排查一下,还真找到了,看下这个函数:
- status_t SurfaceTexture::setBufferCount(int bufferCount) {
- ST_LOGV("setBufferCount: count=%d", bufferCount);
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- if (bufferCount > NUM_BUFFER_SLOTS) {
- ST_LOGE("setBufferCount: bufferCount larger than slots available");
- return BAD_VALUE;
- }
- // Error out if the user has dequeued buffers
- for (int i=0 ; i<mBufferCount ; i++) {
- if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
- ST_LOGE("setBufferCount: client owns some buffers");
- return -EINVAL;
- }
- }
- const int minBufferSlots = mSynchronousMode ?
- MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
- if (bufferCount == 0) {
- mClientBufferCount = 0;
- bufferCount = (mServerBufferCount >= minBufferSlots) ?
- mServerBufferCount : minBufferSlots;
- return setBufferCountServerLocked(bufferCount);
- }
- if (bufferCount < minBufferSlots) {
- ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
- "minimum (%d)", bufferCount, minBufferSlots);
- return BAD_VALUE;
- }
- // here we're guaranteed that the client doesn't have dequeued buffers
- // and will release all of its buffer references.
- freeAllBuffersLocked();
- mBufferCount = bufferCount;
- mClientBufferCount = bufferCount;
- mCurrentTexture = INVALID_BUFFER_SLOT;
- mQueue.clear();
- mDequeueCondition.signal();
- return OK;
- }
找到问题后,在freeAllBuffersLocked()调用之前,将mQueue给抽干一下,等使用的client都用完了再free就好了。
修改之后,再也没有碰到此类错误了。
当然此问题的排查和解决过程没这么顺利,也是搞了好几天的。 解决方法和问题原因也就不细说了,碰到并准备捉这个虫的同学应该会看明白的。
呵呵,这又是可以归结为 多线程同步/状态机 的问题,基本上目前我在Android碰到的严重问题都是这类了
版权声明:本文为博主原创文章,未经博主允许不得转载。
Android的BUG(二) - SurfaceTexture中的野指针的更多相关文章
- C中的野指针—如何避免
转自:http://www.cnblogs.com/viviwind/archive/2012/08/14/2638810.html 先看一个例子: struct student{ char* nam ...
- OC中的野指针(僵尸指针)
涉及到内存管理问题的都是类类型的变量,而在OC中我们操纵这些对象都是通过操纵指向他们的指针来完成的,一致很多时候会忽略指针存在.比如定义UIView * view = [[UIView alloc]i ...
- OC中的野指针,空指针,nil,Nil,NULL,NSNULL小结
周末与一个老朋友吃饭聊天,因为他正在培训班学习iOS开发,就随便聊了几句,发现自己OC基础上的欠缺和一些知识点的混淆.特此整理如下. 1.空指针 没有存储任何内存地址的指针就称为空指针(NULL指针) ...
- Android 短信模块分析(二) MMS中四大组件核心功能详解
接下来的分析先从MMS中四大组件(Activity ,BroadCastReceiver,Service,ContentProvider),也是MMS中最核心的部分入手: 一. Activity 1 ...
- C程序中可怕的野指针
一.疑问点指针是C语言一个很强大的功能,同时也是很容易让人犯错的一个功能,用错了指针,轻者只是报个错,重者可能整个系统都崩溃了.下面是大家在编写C程序时,经常遇到的一种错误的使用方法,也许在你的学习和 ...
- C程序疑问解答 ——可怕的野指针
本篇为原创,禁止任何形式的他用! 一.疑问点 指针是C语言一个很强大的功能,同时也是很容易让人犯错的一个功能,用错了指针,轻者只是报个错,重者可能整个系统都崩溃了.下面是大家在编写C程 ...
- iOS为真机调试增加scribble来定位野指针
尽管在ARC中,野指针出现的频率已经大大降低了,但是仍然会有野指针困扰着我们. 在模拟器调试中,我们可以开启scribble或者zombieObject来将已经释放的内存填充无意义的内容,能够将一些非 ...
- C++ -> 在使用动态链表和异质链表产生野指针的步骤
C++ -> 在使用动态链表和异质链表产生野指针的步骤 使用异质链表产生野指针的情况,下面是修改书本的例子: ------------------------------------------ ...
- Android For JNI(二)——C语言中的数据类型,输出,输入函数以及操作内存地址,内存修改器
Android For JNI(二)--C语言中的数据类型,输出,输入函数以及操作内存地址,内存修改器 当我们把Hello World写完之后,我们就可以迈入C的大门了,今天就来讲讲基本的一些数据类型 ...
随机推荐
- 宣布正式发布 Windows Azure 上的 Oracle 软件以及 Windows Azure Traffic Manager 更新
Windows Azure 的核心原则之一就是为客户提供一个开放.灵活的平台.今天是一个令人振奋的里程碑,因为我们与 Oracle 的合作又向前迈进了一步.Oracle Database.Ora ...
- 外网訪问内网应用实现之无公网IP、多port、固定port、UDP等应用的实现方法
有公网IP时,能够通过路由映射来实现外网訪问内网.然,当没有公网IP时,怎样实现外网訪问内网应用? 硬件路由方法因为无公网不可行,能够使用软件port映射的方法.如开放的NAT123全port映射. ...
- 深入分析MySQL ERROR 1045 (28000)
这几天在MySQL新建用户后.出现訪问拒绝的问题,错误码为ERROR 1045(28000).在网上搜索了非常久.找到了非常多解决的方法,但非常遗憾的是这么多办法没有一个能解决该问题.尽管出现的错误码 ...
- GDB命令行最基本操作
程序启动: A.冷启动 gdb program e.g., gdb ./cs gdb –p pid e.g., gdb –p `pidof c ...
- 几种经典排序算法的JS实现
一.冒泡排序 function BubbleSort(array) { var length = array.length; for (var i = length - 1; i > 0; i- ...
- 优雅的python
在知乎上看到的问题--python有哪些优雅的代码实现. 下面的代码大概也算不上优雅. 一下代码在python3中实现 更多内容可见:http://book.pythontips.com/en/lat ...
- 浅谈JDBC(一)
一.JDBC技术引言 1.什么是JDBC技术 提供了一套接口规范,利用java代码进行数据库操作. 2.JDBC技术的核心思想 对于程序员来说,代码访问数据库分为三个步骤:1.通过数据库的账号密码.2 ...
- LeetCode 二叉树的最小深度
计算二叉树的最小深度.最小深度定义为从root到叶子节点的最小路径. public class Solution { public int run(TreeNode root) { if(root = ...
- JDBC_获取插入记录的主键值
<span style="font-size:24px;">package src.com.JDBC2DAO.java; import static org.junit ...
- centos主机建立ssh互信
ssh-keygen 生成密钥 1.ssh-keygen -t rsa 可以加密和签名 rsa 只能加密不能签名 2.ssh-copy-id -i /root/.ssh/id_rsa.pub USER ...