summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger/SurfaceFlinger.cpp
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2013-06-05 14:30:54 -0700
committerMathias Agopian <mathias@google.com>2013-06-05 14:38:23 -0700
commit7cc6df59572582652078df5aeac9e6c67d7fa81e (patch)
treef3c70a7e392c8c5a9cb0d2762709c9d1cbe6db8e /services/surfaceflinger/SurfaceFlinger.cpp
parentae772278fe52335b730442f3d86307787dea807e (diff)
downloadframeworks_native-7cc6df59572582652078df5aeac9e6c67d7fa81e.zip
frameworks_native-7cc6df59572582652078df5aeac9e6c67d7fa81e.tar.gz
frameworks_native-7cc6df59572582652078df5aeac9e6c67d7fa81e.tar.bz2
fix a possible deadlock when removing a layer and destroying a client
generally the last reference to a Layer is released in commitTransaction() with mStateLock held. Layer itself only holds weak references to Client, however, ~Layer() briefly promotes this weak reference -- during that time the all other strong references to that Client go away, ~Layer is left with the last one... then hell breaks loose as ~Client is called, which in turn needs to acquire mStateLock. We fix this by holding a temporary copy of the drawing state during the transaction so that the side-effects of copying the current state into the drawing state are seen only after mStateLock has been released. Bug: 9106453 Change-Id: Ic5348ac12283500ead87286a37565e8da35f1db2
Diffstat (limited to 'services/surfaceflinger/SurfaceFlinger.cpp')
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp6
1 files changed, 6 insertions, 0 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index fbd9f25..8291da0 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1056,6 +1056,12 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
{
ATRACE_CALL();
+ // here we keep a copy of the drawing state (that is the state that's
+ // going to be overwritten by handleTransactionLocked()) outside of
+ // mStateLock so that the side-effects of the State assignment
+ // don't happen with mStateLock held (which can cause deadlocks).
+ State drawingState(mDrawingState);
+
Mutex::Autolock _l(mStateLock);
const nsecs_t now = systemTime();
mDebugInTransaction = now;