From e5886d917807d56fed07cd8e88b9be268d70368e Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 5 Jun 2013 14:30:54 -0700 Subject: [PATCH] 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 --- services/surfaceflinger/SurfaceFlinger.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index ef0d52146..e4d3c5f38 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1037,6 +1037,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;