diff options
| author | 2019-05-30 09:20:35 -0700 | |
|---|---|---|
| committer | 2019-05-30 09:20:35 -0700 | |
| commit | 0fafdb81ae408c155607151f27ca51622cdeb089 (patch) | |
| tree | e87e615f53858f2037afcaa55e76e6a6040711a7 | |
| parent | 113db1050ff7e0fe00fb045fa98f20e75b3ff599 (diff) | |
| parent | 1db00e0af02d17b4894d6591adcc20477d8f689c (diff) | |
Merge "transactions: fix mutex deadlock on layer death" into qt-dev
am: 1db00e0af0
Change-Id: I009654a8678a1d0c36474c7e0856cbde384d7b3d
| -rw-r--r-- | services/surfaceflinger/TransactionCompletedThread.cpp | 17 |
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(); } } |