From 51e4dc89f0e9b93f0be3204181caa9bef5376746 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Fri, 1 Oct 2021 15:32:33 -0700 Subject: BlastBufferQueue: Fix async worker deadlock The async onBufferReleased callback can trigger another onBufferReleased which will end up deadlocking the async worker thread. Fix this by executing the callbacks outside the lock. Test: atest android.media.cts.MediaSyncTest#testPlaybackRateDouble --rerun-util-failure 100 Fixes: 201604213 Change-Id: I40d163c3644c6a0128936cf41e8bf8969766d9da --- libs/gui/BLASTBufferQueue.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'libs/gui/BLASTBufferQueue.cpp') diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index d1f57b03bc..5b9d912723 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -738,14 +738,26 @@ private: std::unique_lock lock(mMutex); while (!mDone) { while (!mRunnables.empty()) { - std::function runnable = mRunnables.front(); - mRunnables.pop_front(); - runnable(); + std::deque> runnables = std::move(mRunnables); + mRunnables.clear(); + lock.unlock(); + // Run outside the lock since the runnable might trigger another + // post to the async worker. + execute(runnables); + lock.lock(); } mCv.wait(lock); } } + void execute(std::deque>& runnables) { + while (!runnables.empty()) { + std::function runnable = runnables.front(); + runnables.pop_front(); + runnable(); + } + } + public: AsyncWorker() : Singleton() { mThread = std::thread(&AsyncWorker::run, this); } -- cgit v1.2.3-59-g8ed1b