Bug 1171496 - Make GMPParent hold a self ref while GMP child process is alive. a=lizzard
authorChris Pearce <cpearce@mozilla.com>
Tue, 16 Jun 2015 17:24:00 -0400
changeset 267753 46b6c71bb1c1b329c2c03614f48dfaa23abfa4da
parent 267752 68aa36e9b5fc173ec1900fa005f88ba4aac7742e
child 267754 654e69b95ed70ae9be85c2a6361772aca56934d0
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslizzard
bugs1171496
milestone39.0
Bug 1171496 - Make GMPParent hold a self ref while GMP child process is alive. a=lizzard
dom/media/gmp/GMPParent.cpp
dom/media/gmp/GMPParent.h
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -55,28 +55,31 @@ GMPParent::GMPParent()
   , mAbnormalShutdownInProgress(false)
   , mIsBlockingDeletion(false)
   , mCanDecrypt(false)
   , mAsyncShutdownRequired(false)
   , mAsyncShutdownInProgress(false)
 #ifdef PR_LOGGING
   , mChildPid(0)
 #endif
+  , mHoldingSelfRef(false)
 {
   LOGD("GMPParent ctor");
   // Use the parent address to identify it.
   // We could use any unique-to-the-parent value.
   mPluginId.AppendInt(reinterpret_cast<uint64_t>(this));
 }
 
 GMPParent::~GMPParent()
 {
   // Can't Close or Destroy the process here, since destruction is MainThread only
   MOZ_ASSERT(NS_IsMainThread());
   LOGD("GMPParent dtor");
+
+  MOZ_ASSERT(!mProcess);
 }
 
 void
 GMPParent::CheckThread()
 {
   MOZ_ASSERT(mGMPThread == NS_GetCurrentThread());
 }
 
@@ -178,16 +181,23 @@ GMPParent::LoadProcess()
       mProcess = nullptr;
       return NS_ERROR_FAILURE;
     }
     LOGD("%s: Sent StartPlugin to child process", __FUNCTION__);
   }
 
   mState = GMPStateLoaded;
 
+  // Hold a self ref while the child process is alive. This ensures that
+  // during shutdown the GMPParent stays we stay alive long enough to
+  // terminate the child process.
+  MOZ_ASSERT(!mHoldingSelfRef);
+  mHoldingSelfRef = true;
+  AddRef();
+
   return NS_OK;
 }
 
 void
 AbortWaitingForGMPAsyncShutdown(nsITimer* aTimer, void* aClosure)
 {
   NS_WARNING("Timed out waiting for GMP async shutdown!");
   GMPParent* parent = reinterpret_cast<GMPParent*>(aClosure);
@@ -426,16 +436,20 @@ GMPParent::DeleteProcess()
   LOGD("%s: Shut down process", __FUNCTION__);
   mProcess = nullptr;
   mState = GMPStateNotLoaded;
 
   NS_DispatchToMainThread(
     new NotifyGMPShutdownTask(NS_ConvertUTF8toUTF16(mNodeId)),
     NS_DISPATCH_NORMAL);
 
+  if (mHoldingSelfRef) {
+    Release();
+    mHoldingSelfRef = false;
+  }
 }
 
 void
 GMPParent::VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder)
 {
   MOZ_ASSERT(GMPThread() == NS_GetCurrentThread());
 
   // If the constructor fails, we'll get called before it's added
--- a/dom/media/gmp/GMPParent.h
+++ b/dom/media/gmp/GMPParent.h
@@ -210,14 +210,20 @@ private:
   nsAutoCString mNodeId;
 
   bool mAsyncShutdownRequired;
   bool mAsyncShutdownInProgress;
 
 #ifdef PR_LOGGING
   int mChildPid;
 #endif
+
+  // We hold a self reference to ourself while the child process is alive.
+  // This ensures that if the GMPService tries to shut us down and drops
+  // its reference to us, we stay alive long enough for the child process
+  // to terminate gracefully.
+  bool mHoldingSelfRef;
 };
 
 } // namespace gmp
 } // namespace mozilla
 
 #endif // GMPParent_h_