Don't call Close twice when the GPU process unexpectedly terminates. (bug 1282348 part 6, r=billm)
authorDavid Anderson <danderson@mozilla.com>
Sun, 17 Jul 2016 21:24:28 -0700
changeset 330402 0520526e9ff334a64a26895802b3661f3ba8b682
parent 330401 e6bd9062617fecf80cf520885e367776d02c9745
child 330403 39636df7a0fe56efe6e0480df7cbb707d18c70b3
push id9858
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 14:37:10 +0000
treeherdermozilla-aurora@203106ef6cb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1282348
milestone50.0a1
Don't call Close twice when the GPU process unexpectedly terminates. (bug 1282348 part 6, r=billm)
gfx/ipc/GPUProcessHost.cpp
gfx/ipc/GPUProcessHost.h
--- a/gfx/ipc/GPUProcessHost.cpp
+++ b/gfx/ipc/GPUProcessHost.cpp
@@ -14,17 +14,18 @@ namespace mozilla {
 namespace gfx {
 
 GPUProcessHost::GPUProcessHost(Listener* aListener)
  : GeckoChildProcessHost(GeckoProcessType_GPU),
    mListener(aListener),
    mTaskFactory(this),
    mLaunchPhase(LaunchPhase::Unlaunched),
    mProcessToken(0),
-   mShutdownRequested(false)
+   mShutdownRequested(false),
+   mChannelClosed(false)
 {
   MOZ_COUNT_CTOR(GPUProcessHost);
 }
 
 GPUProcessHost::~GPUProcessHost()
 {
   MOZ_COUNT_DTOR(GPUProcessHost);
 }
@@ -143,35 +144,44 @@ GPUProcessHost::Shutdown()
   mListener = nullptr;
 
   if (mGPUChild) {
     // OnChannelClosed uses this to check if the shutdown was expected or
     // unexpected.
     mShutdownRequested = true;
 
 #ifdef NS_FREE_PERMANENT_DATA
-    mGPUChild->Close();
+    // The channel might already be closed if we got here unexpectedly.
+    if (!mChannelClosed) {
+      mGPUChild->Close();
+    }
 #else
     // No need to communicate shutdown, the GPU process doesn't need to
     // communicate anything back.
     KillHard("NormalShutdown");
 #endif
 
-    // Wait for ActorDestroy.
+    // If we're shutting down unexpectedly, we're in the middle of handling an
+    // ActorDestroy for PGPUChild, which is still on the stack. We'll return
+    // back to OnChannelClosed.
+    //
+    // Otherwise, we'll wait for OnChannelClose to be called whenever PGPUChild
+    // acknowledges shutdown.
     return;
   }
 
   DestroyProcess();
 }
 
 void
 GPUProcessHost::OnChannelClosed()
 {
   if (!mShutdownRequested) {
     // This is an unclean shutdown. Notify our listener that we're going away.
+    mChannelClosed = true;
     if (mListener) {
       mListener->OnProcessUnexpectedShutdown(this);
     }
   }
 
   // Release the actor.
   GPUChild::Destroy(Move(mGPUChild));
   MOZ_ASSERT(!mGPUChild);
--- a/gfx/ipc/GPUProcessHost.h
+++ b/gfx/ipc/GPUProcessHost.h
@@ -116,14 +116,15 @@ private:
     Complete
   };
   LaunchPhase mLaunchPhase;
 
   UniquePtr<GPUChild> mGPUChild;
   uint64_t mProcessToken;
 
   bool mShutdownRequested;
+  bool mChannelClosed;
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif // _include_mozilla_gfx_ipc_GPUProcessHost_h_