zoukankan      html  css  js  c++  java
  • Android的BUG(二)

    当初遇到这个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 不为空的可能? 排查一下,还真找到了,看下这个函数:

    1. status_t SurfaceTexture::setBufferCount(int bufferCount) {  
    2.     ST_LOGV("setBufferCount: count=%d", bufferCount);  
    3.     Mutex::Autolock lock(mMutex);  
    4.   
    5.     if (mAbandoned) {  
    6.         ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!");  
    7.         return NO_INIT;  
    8.     }  
    9.     if (bufferCount > NUM_BUFFER_SLOTS) {  
    10.         ST_LOGE("setBufferCount: bufferCount larger than slots available");  
    11.         return BAD_VALUE;  
    12.     }  
    13.   
    14.     // Error out if the user has dequeued buffers  
    15.     for (int i=0 ; i<mBufferCount ; i++) {  
    16.         if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {  
    17.             ST_LOGE("setBufferCount: client owns some buffers");  
    18.             return -EINVAL;  
    19.         }  
    20.     }  
    21.   
    22.     const int minBufferSlots = mSynchronousMode ?  
    23.             MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;  
    24.     if (bufferCount == 0) {  
    25.         mClientBufferCount = 0;  
    26.         bufferCount = (mServerBufferCount >= minBufferSlots) ?  
    27.                 mServerBufferCount : minBufferSlots;  
    28.         return setBufferCountServerLocked(bufferCount);  
    29.     }  
    30.   
    31.     if (bufferCount < minBufferSlots) {  
    32.         ST_LOGE("setBufferCount: requested buffer count (%d) is less than "  
    33.                 "minimum (%d)", bufferCount, minBufferSlots);  
    34.         return BAD_VALUE;  
    35.     }  
    36.   
    37.     // here we're guaranteed that the client doesn't have dequeued buffers  
    38.     // and will release all of its buffer references.  
    39.     freeAllBuffersLocked();  
    40.     mBufferCount = bufferCount;  
    41.     mClientBufferCount = bufferCount;  
    42.     mCurrentTexture = INVALID_BUFFER_SLOT;  
    43.     mQueue.clear();  
    44.     mDequeueCondition.signal();  
    45.     return OK;  
    46. }  


    找到问题后,在freeAllBuffersLocked()调用之前,将mQueue给抽干一下,等使用的client都用完了再free就好了。

    修改之后,再也没有碰到此类错误了。

    当然此问题的排查和解决过程没这么顺利,也是搞了好几天的。 解决方法和问题原因也就不细说了,碰到并准备捉这个虫的同学应该会看明白的。

    呵呵,这又是可以归结为 多线程同步/状态机 的问题,基本上目前我在Android碰到的严重问题都是这类了

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    多项式 Wannafly挑战赛22
    L. Twice Equation ACM Nanning 2017
    我们身边的大数据
    js_隔10秒发送验证码(setInterrval定时器)
    js_定时器(setInterval)
    VS调试相关
    afx_msg与消息映射机制
    ON_COMMAND,ON_MESSAGE和ON_NOTIFY的区别
    条款4:确定对象在被使用前已经被初始化
    用doxygen+graphviz生成函数调用流程图
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4925081.html
Copyright © 2011-2022 走看看