From 19cd146ac0f8b13c811ef476a48ece9d9b87e285 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 Bug: 201604213 Change-Id: I40d163c3644c6a0128936cf41e8bf8969766d9da Merged-In: 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 5b59c592df..9baf79b443 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -731,14 +731,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