diff options
| author | 2021-10-01 15:32:33 -0700 | |
|---|---|---|
| committer | 2022-02-04 22:57:06 +0000 | |
| commit | 19cd146ac0f8b13c811ef476a48ece9d9b87e285 (patch) | |
| tree | 1cacdc15879e494f5e818bdcb8b8439082659245 /libs/gui/BLASTBufferQueue.cpp | |
| parent | 415611420c90688c27da9eaf1e57b592be82d754 (diff) | |
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
Diffstat (limited to 'libs/gui/BLASTBufferQueue.cpp')
| -rw-r--r-- | libs/gui/BLASTBufferQueue.cpp | 18 |
1 files changed, 15 insertions, 3 deletions
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<std::mutex> lock(mMutex); while (!mDone) { while (!mRunnables.empty()) { - std::function<void()> runnable = mRunnables.front(); - mRunnables.pop_front(); - runnable(); + std::deque<std::function<void()>> 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<std::function<void()>>& runnables) { + while (!runnables.empty()) { + std::function<void()> runnable = runnables.front(); + runnables.pop_front(); + runnable(); + } + } + public: AsyncWorker() : Singleton<AsyncWorker>() { mThread = std::thread(&AsyncWorker::run, this); } |