fix race condition that can cause a use after free Backported from 12a0ccd6f7201bac706d903ac3f436c4358fe203. Bug: 33004354 Test: manual Change-Id: I9b38ee644b02268c9b995a330db758aa2e568399 (cherry picked from commit 59485525a6047453e6ba16c03989381e2a0d56ec)
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 09e7cb6..56cdf26 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp
@@ -913,7 +913,11 @@ // Call back without the main BufferQueue lock held, but with the callback // lock held so we can ensure that callbacks occur in order - { + + int connectedApi; + sp<Fence> lastQueuedFence; + + { // scope for the lock Mutex::Autolock lock(mCallbackMutex); while (callbackTicket != mCurrentCallbackTicket) { mCallbackCondition.wait(mCallbackMutex); @@ -925,20 +929,24 @@ frameReplacedListener->onFrameReplaced(item); } + connectedApi = mCore->mConnectedApi; + lastQueuedFence = std::move(mLastQueueBufferFence); + + mLastQueueBufferFence = std::move(fence); + mLastQueuedCrop = item.mCrop; + mLastQueuedTransform = item.mTransform; + ++mCurrentCallbackTicket; mCallbackCondition.broadcast(); } // Wait without lock held - if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) { + if (connectedApi == NATIVE_WINDOW_API_EGL) { // Waiting here allows for two full buffers to be queued but not a // third. In the event that frames take varying time, this makes a // small trade-off in favor of latency rather than throughput. - mLastQueueBufferFence->waitForever("Throttling EGL Production"); + lastQueuedFence->waitForever("Throttling EGL Production"); } - mLastQueueBufferFence = fence; - mLastQueuedCrop = item.mCrop; - mLastQueuedTransform = item.mTransform; return NO_ERROR; }