summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Marissa Wall <marissaw@google.com> 2019-05-30 09:20:35 -0700
committer android-build-merger <android-build-merger@google.com> 2019-05-30 09:20:35 -0700
commit0fafdb81ae408c155607151f27ca51622cdeb089 (patch)
treee87e615f53858f2037afcaa55e76e6a6040711a7
parent113db1050ff7e0fe00fb045fa98f20e75b3ff599 (diff)
parent1db00e0af02d17b4894d6591adcc20477d8f689c (diff)
Merge "transactions: fix mutex deadlock on layer death" into qt-dev
am: 1db00e0af0 Change-Id: I009654a8678a1d0c36474c7e0856cbde384d7b3d
-rw-r--r--services/surfaceflinger/TransactionCompletedThread.cpp17
1 files changed, 17 insertions, 0 deletions
diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp
index b1bf4e20d3..5cf8eb1a1d 100644
--- a/services/surfaceflinger/TransactionCompletedThread.cpp
+++ b/services/surfaceflinger/TransactionCompletedThread.cpp
@@ -219,6 +219,7 @@ void TransactionCompletedThread::threadMain() {
while (mKeepRunning) {
mConditionVariable.wait(mMutex);
+ std::vector<ListenerStats> completedListenerStats;
// For each listener
auto completedTransactionsItr = mCompletedTransactions.begin();
@@ -264,11 +265,27 @@ void TransactionCompletedThread::threadMain() {
} else {
completedTransactionsItr++;
}
+
+ completedListenerStats.push_back(std::move(listenerStats));
}
if (mPresentFence) {
mPresentFence.clear();
}
+
+ // If everyone else has dropped their reference to a layer and its listener is dead,
+ // we are about to cause the layer to be deleted. If this happens at the wrong time and
+ // we are holding mMutex, we will cause a deadlock.
+ //
+ // The deadlock happens because this thread is holding on to mMutex and when we delete
+ // the layer, it grabs SF's mStateLock. A different SF binder thread grabs mStateLock,
+ // then call's TransactionCompletedThread::run() which tries to grab mMutex.
+ //
+ // To avoid this deadlock, we need to unlock mMutex when dropping our last reference to
+ // to the layer.
+ mMutex.unlock();
+ completedListenerStats.clear();
+ mMutex.lock();
}
}