summaryrefslogtreecommitdiff
path: root/libs/gui/BLASTBufferQueue.cpp
diff options
context:
space:
mode:
author Vishnu Nair <vishnun@google.com> 2021-10-01 15:32:33 -0700
committer Vishnu Nair <vishnun@google.com> 2021-10-01 15:32:33 -0700
commit51e4dc89f0e9b93f0be3204181caa9bef5376746 (patch)
tree86126ff2e057e2bb25d3a4de6e61fa684b0ba9f1 /libs/gui/BLASTBufferQueue.cpp
parent979587e1f43c27557eb68c1d4031edd57100f553 (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 Fixes: 201604213 Change-Id: I40d163c3644c6a0128936cf41e8bf8969766d9da
Diffstat (limited to 'libs/gui/BLASTBufferQueue.cpp')
-rw-r--r--libs/gui/BLASTBufferQueue.cpp18
1 files changed, 15 insertions, 3 deletions
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<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); }