OSDN Git Service

Fix deadlock when transitioning to vr flinger
authorSteven Thomas <steventhomas@google.com>
Thu, 28 Sep 2017 22:30:23 +0000 (15:30 -0700)
committerSteven Thomas <steventhomas@google.com>
Fri, 29 Sep 2017 18:03:15 +0000 (11:03 -0700)
If we were unlucky with the timing when switching to vr flinger we would
sometimes deadlock. The vr dispatch thread would request the display
from surface flinger, locking mStateLock in the process. mStateLock was
being held by the surface flinger main thread, which was processing a
previous request to switch to vr flinger. The main thread was trying to
connect to the vr hardware composer service, which sent a request to the
vr dispatch thread as part of its initialization, leading to the
deadlock.

The deadlock is easily fixed by posting a message to request the vr
flinger switch to the surface flinger main thread, instead of doing it
on the vr dispatch thread.

Bug: 66916578

Test: Confirmed I can still get into/out of vr flinger on
Marlin. There's no longer code to acquire mStateLock in the vr dispatch
thread, so the deadlock is no longer possible.

Change-Id: I3de5476f698ed798f6b9afe927cc733f0f38c56e

services/surfaceflinger/SurfaceFlinger.cpp

index 12205af..c05ac8a 100644 (file)
@@ -604,11 +604,18 @@ void SurfaceFlinger::init() {
 
     if (useVrFlinger) {
         auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
-            ALOGI("VR request display mode: requestDisplay=%d", requestDisplay);
-            mVrFlingerRequestsDisplay = requestDisplay;
-            ConditionalLock _l(mStateLock,
-                    std::this_thread::get_id() != mMainThreadId);
-            signalTransaction();
+            // This callback is called from the vr flinger dispatch thread. We
+            // need to call signalTransaction(), which requires holding
+            // mStateLock when we're not on the main thread. Acquiring
+            // mStateLock from the vr flinger dispatch thread might trigger a
+            // deadlock in surface flinger (see b/66916578), so post a message
+            // to be handled on the main thread instead.
+            sp<LambdaMessage> message = new LambdaMessage([=]() {
+                ALOGI("VR request display mode: requestDisplay=%d", requestDisplay);
+                mVrFlingerRequestsDisplay = requestDisplay;
+                signalTransaction();
+            });
+            postMessageAsync(message);
         };
         mVrFlinger = dvr::VrFlinger::Create(mHwc->getComposer(),
                                             vrFlingerRequestDisplayCallback);