Android的BUG(二) – SurfaceTexture中的野指標

來源:互聯網
上載者:User

當初遇到這個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 emptyD/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碰到的嚴重問題都是這類了

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.