Bug 1227407 - Ensure Cameras is alive before calling through it. r=jesup
authorGian-Carlo Pascutto <gcp@mozilla.com>
Thu, 03 Dec 2015 15:11:07 +0100
changeset 275462 7cca9ddc7f9a5c98df1e1f84e251c94e2513e50d
parent 275461 6139297dfb98c010a52c25b1bae658f84db2cd6e
child 275463 cd3ee5f0e8f63480cd1493aaf6c2b452acb8be02
push id68848
push usergpascutto@mozilla.com
push dateThu, 03 Dec 2015 14:11:29 +0000
treeherdermozilla-inbound@cd3ee5f0e8f6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs1227407
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1227407 - Ensure Cameras is alive before calling through it. r=jesup
dom/media/systemservices/CamerasChild.cpp
--- a/dom/media/systemservices/CamerasChild.cpp
+++ b/dom/media/systemservices/CamerasChild.cpp
@@ -123,27 +123,26 @@ public:
     // We will be returning the resulting pointer (synchronously) to our caller.
     mCamerasChild =
       static_cast<mozilla::camera::CamerasChild*>(existingBackgroundChild->SendPCamerasConstructor());
 
     return NS_OK;
   }
 
   CamerasChild* GetCamerasChild() {
-    MOZ_ASSERT(mCamerasChild);
     return mCamerasChild;
   }
 
 private:
   CamerasChild* mCamerasChild;
 };
 
 static CamerasChild*
-Cameras() {
-  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+GetCamerasChild() {
+  CamerasSingleton::Mutex().AssertCurrentThreadOwns();
   if (!CamerasSingleton::Child()) {
     MOZ_ASSERT(!NS_IsMainThread(), "Should not be on the main Thread");
     MOZ_ASSERT(!CamerasSingleton::Thread());
     LOG(("No sCameras, setting up IPC Thread"));
     nsresult rv = NS_NewNamedThread("Cameras IPC",
                                     getter_AddRefs(CamerasSingleton::Thread()));
     if (NS_FAILED(rv)) {
       LOG(("Error launching IPC Thread"));
@@ -157,17 +156,19 @@ Cameras() {
     // We block until the following happens in the Cameras IPC thread:
     // 1) Creation of PBackground finishes
     // 2) Creation of PCameras finishes by sending a message to the parent
     RefPtr<InitializeIPCThread> runnable = new InitializeIPCThread();
     RefPtr<SyncRunnable> sr = new SyncRunnable(runnable);
     sr->DispatchToThread(CamerasSingleton::Thread());
     CamerasSingleton::Child() = runnable->GetCamerasChild();
   }
-  MOZ_ASSERT(CamerasSingleton::Child());
+  if (!CamerasSingleton::Child()) {
+    LOG(("Failed to set up CamerasChild, are we in shutdown?"));
+  }
   return CamerasSingleton::Child();
 }
 
 bool
 CamerasChild::RecvReplyFailure(void)
 {
   LOG((__PRETTY_FUNCTION__));
   MonitorAutoLock monitor(mReplyMonitor);
@@ -185,17 +186,23 @@ CamerasChild::RecvReplySuccess(void)
   mReceivedReply = true;
   mReplySuccess = true;
   monitor.Notify();
   return true;
 }
 
 int NumberOfCapabilities(CaptureEngine aCapEngine, const char* deviceUniqueIdUTF8)
 {
-  return Cameras()->NumberOfCapabilities(aCapEngine, deviceUniqueIdUTF8);
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  CamerasChild* child = GetCamerasChild();
+  if (child) {
+    return child->NumberOfCapabilities(aCapEngine, deviceUniqueIdUTF8);
+  } else {
+    return 0;
+  }
 }
 
 bool
 CamerasChild::RecvReplyNumberOfCapabilities(const int& numdev)
 {
   LOG((__PRETTY_FUNCTION__));
   MonitorAutoLock monitor(mReplyMonitor);
   mReceivedReply = true;
@@ -204,20 +211,18 @@ CamerasChild::RecvReplyNumberOfCapabilit
   monitor.Notify();
   return true;
 }
 
 bool
 CamerasChild::DispatchToParent(nsIRunnable* aRunnable,
                                MonitorAutoLock& aMonitor)
 {
-  {
-    OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
-    CamerasSingleton::Thread()->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
-  }
+  CamerasSingleton::Mutex().AssertCurrentThreadOwns();
+  CamerasSingleton::Thread()->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
   // We can't see if the send worked, so we need to be able to bail
   // out on shutdown (when it failed and we won't get a reply).
   if (!mIPCIsAlive) {
     return false;
   }
   // Guard against spurious wakeups.
   mReceivedReply = false;
   // Wait for a reply
@@ -255,17 +260,23 @@ CamerasChild::NumberOfCapabilities(Captu
     return 0;
   }
   LOG(("Capture capability count: %d", mReplyInteger));
   return mReplyInteger;
 }
 
 int NumberOfCaptureDevices(CaptureEngine aCapEngine)
 {
-  return Cameras()->NumberOfCaptureDevices(aCapEngine);
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  CamerasChild* child = GetCamerasChild();
+  if (child) {
+    return child->NumberOfCaptureDevices(aCapEngine);
+  } else {
+    return 0;
+  }
 }
 
 int
 CamerasChild::NumberOfCaptureDevices(CaptureEngine aCapEngine)
 {
   MutexAutoLock requestLock(mRequestMutex);
   LOG((__PRETTY_FUNCTION__));
   nsCOMPtr<nsIRunnable> runnable =
@@ -295,20 +306,26 @@ CamerasChild::RecvReplyNumberOfCaptureDe
   monitor.Notify();
   return true;
 }
 
 int GetCaptureCapability(CaptureEngine aCapEngine, const char* unique_idUTF8,
                          const unsigned int capability_number,
                          webrtc::CaptureCapability& capability)
 {
-  return Cameras()->GetCaptureCapability(aCapEngine,
-                                         unique_idUTF8,
-                                         capability_number,
-                                         capability);
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  CamerasChild* child = GetCamerasChild();
+  if (child) {
+    return child->GetCaptureCapability(aCapEngine,
+                                       unique_idUTF8,
+                                       capability_number,
+                                       capability);
+  } else {
+    return -1;
+  }
 }
 
 int
 CamerasChild::GetCaptureCapability(CaptureEngine aCapEngine,
                                    const char* unique_idUTF8,
                                    const unsigned int capability_number,
                                    webrtc::CaptureCapability& capability)
 {
@@ -350,22 +367,28 @@ CamerasChild::RecvReplyGetCaptureCapabil
 
 
 int GetCaptureDevice(CaptureEngine aCapEngine,
                      unsigned int list_number, char* device_nameUTF8,
                      const unsigned int device_nameUTF8Length,
                      char* unique_idUTF8,
                      const unsigned int unique_idUTF8Length)
 {
-  return Cameras()->GetCaptureDevice(aCapEngine,
-                                     list_number,
-                                     device_nameUTF8,
-                                     device_nameUTF8Length,
-                                     unique_idUTF8,
-                                     unique_idUTF8Length);
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  CamerasChild* child = GetCamerasChild();
+  if (child) {
+    return child->GetCaptureDevice(aCapEngine,
+                                   list_number,
+                                   device_nameUTF8,
+                                   device_nameUTF8Length,
+                                   unique_idUTF8,
+                                   unique_idUTF8Length);
+  } else {
+    return -1;
+  }
 }
 
 int
 CamerasChild::GetCaptureDevice(CaptureEngine aCapEngine,
                                unsigned int list_number, char* device_nameUTF8,
                                const unsigned int device_nameUTF8Length,
                                char* unique_idUTF8,
                                const unsigned int unique_idUTF8Length)
@@ -404,20 +427,26 @@ CamerasChild::RecvReplyGetCaptureDevice(
   return true;
 }
 
 int AllocateCaptureDevice(CaptureEngine aCapEngine,
                           const char* unique_idUTF8,
                           const unsigned int unique_idUTF8Length,
                           int& capture_id)
 {
-  return Cameras()->AllocateCaptureDevice(aCapEngine,
-                                          unique_idUTF8,
-                                          unique_idUTF8Length,
-                                          capture_id);
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  CamerasChild* child = GetCamerasChild();
+  if (child) {
+    return child->AllocateCaptureDevice(aCapEngine,
+                                        unique_idUTF8,
+                                        unique_idUTF8Length,
+                                        capture_id);
+  } else {
+    return -1;
+  }
 }
 
 int
 CamerasChild::AllocateCaptureDevice(CaptureEngine aCapEngine,
                                     const char* unique_idUTF8,
                                     const unsigned int unique_idUTF8Length,
                                     int& capture_id)
 {
@@ -451,17 +480,23 @@ CamerasChild::RecvReplyAllocateCaptureDe
   mReplySuccess = true;
   mReplyInteger = numdev;
   monitor.Notify();
   return true;
 }
 
 int ReleaseCaptureDevice(CaptureEngine aCapEngine, const int capture_id)
 {
-  return Cameras()->ReleaseCaptureDevice(aCapEngine, capture_id);
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  CamerasChild* child = GetCamerasChild();
+  if (child) {
+    return child->ReleaseCaptureDevice(aCapEngine, capture_id);
+  } else {
+    return -1;
+  }
 }
 
 int
 CamerasChild::ReleaseCaptureDevice(CaptureEngine aCapEngine,
                                    const int capture_id)
 {
   MutexAutoLock requestLock(mRequestMutex);
   LOG((__PRETTY_FUNCTION__));
@@ -504,20 +539,26 @@ CamerasChild::RemoveCallback(const Captu
   }
 }
 
 int StartCapture(CaptureEngine aCapEngine,
                  const int capture_id,
                  webrtc::CaptureCapability& webrtcCaps,
                  webrtc::ExternalRenderer* cb)
 {
-  return Cameras()->StartCapture(aCapEngine,
-                                 capture_id,
-                                 webrtcCaps,
-                                 cb);
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  CamerasChild* child = GetCamerasChild();
+  if (child) {
+    return child->StartCapture(aCapEngine,
+                               capture_id,
+                               webrtcCaps,
+                               cb);
+  } else {
+    return -1;
+  }
 }
 
 int
 CamerasChild::StartCapture(CaptureEngine aCapEngine,
                            const int capture_id,
                            webrtc::CaptureCapability& webrtcCaps,
                            webrtc::ExternalRenderer* cb)
 {
@@ -542,17 +583,23 @@ CamerasChild::StartCapture(CaptureEngine
   if (!DispatchToParent(runnable, monitor)) {
     return -1;
   }
   return 0;
 }
 
 int StopCapture(CaptureEngine aCapEngine, const int capture_id)
 {
-  return Cameras()->StopCapture(aCapEngine, capture_id);
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  CamerasChild* child = GetCamerasChild();
+  if (child) {
+    return child->StopCapture(aCapEngine, capture_id);
+  } else {
+    return -1;
+  }
 }
 
 int
 CamerasChild::StopCapture(CaptureEngine aCapEngine, const int capture_id)
 {
   MutexAutoLock requestLock(mRequestMutex);
   LOG((__PRETTY_FUNCTION__));
   nsCOMPtr<nsIRunnable> runnable =
@@ -568,26 +615,24 @@ CamerasChild::StopCapture(CaptureEngine 
   }
   RemoveCallback(aCapEngine, capture_id);
   return 0;
 }
 
 void
 Shutdown(void)
 {
-  {
-    OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
-    if (!CamerasSingleton::Child()) {
-      // We don't want to cause everything to get fired up if we're
-      // really already shut down.
-      LOG(("Shutdown when already shut down"));
-      return;
-    }
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  if (!CamerasSingleton::Child()) {
+    // We don't want to cause everything to get fired up if we're
+    // really already shut down.
+    LOG(("Shutdown when already shut down"));
+    return;
   }
-  Cameras()->Shutdown();
+  GetCamerasChild()->Shutdown();
 }
 
 class ShutdownRunnable : public nsRunnable {
 public:
   ShutdownRunnable(RefPtr<nsRunnable> aReplyEvent,
                    nsIThread* aReplyThread)
     : mReplyEvent(aReplyEvent), mReplyThread(aReplyThread) {};
 
@@ -610,17 +655,16 @@ void
 CamerasChild::Shutdown()
 {
   {
     MonitorAutoLock monitor(mReplyMonitor);
     mIPCIsAlive = false;
     monitor.NotifyAll();
   }
 
-  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
   if (CamerasSingleton::Thread()) {
     LOG(("Dispatching actor deletion"));
     // Delete the parent actor.
     RefPtr<nsRunnable> deleteRunnable =
       // CamerasChild (this) will remain alive and is only deleted by the
       // IPC layer when SendAllDone returns.
       media::NewRunnableFrom([this]() -> nsresult {
         Unused << this->SendAllDone();
@@ -703,17 +747,20 @@ CamerasChild::CamerasChild()
 
   MOZ_COUNT_CTOR(CamerasChild);
 }
 
 CamerasChild::~CamerasChild()
 {
   LOG(("~CamerasChild: %p", this));
 
-  Shutdown();
+  {
+    OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+    Shutdown();
+  }
 
   MOZ_COUNT_DTOR(CamerasChild);
 }
 
 webrtc::ExternalRenderer* CamerasChild::Callback(CaptureEngine aCapEngine,
                                                  int capture_id)
 {
   for (unsigned int i = 0; i < mCallbacks.Length(); i++) {