Bug 1247236. r=jesup
authorGian-Carlo Pascutto <gcp@mozilla.com>
Thu, 18 Feb 2016 17:25:22 +0100
changeset 331910 92827e1743bccc47d56a4dd312e5035f598262b8
parent 331909 153e8aa293c510f9a56e12d55a2430770fc43c51
child 331911 ded9e2d81845f5b62dfb8035df307d7dc05c14f2
push id11113
push userrjesup@wgate.com
push dateThu, 18 Feb 2016 19:00:12 +0000
reviewersjesup
bugs1247236
milestone47.0a1
Bug 1247236. r=jesup
dom/media/systemservices/CamerasChild.cpp
dom/media/systemservices/CamerasChild.h
--- a/dom/media/systemservices/CamerasChild.cpp
+++ b/dom/media/systemservices/CamerasChild.cpp
@@ -469,23 +469,24 @@ CamerasChild::StopCapture(CaptureEngine 
   }
   return dispatcher.ReturnValue();
 }
 
 void
 Shutdown(void)
 {
   OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
-  if (!CamerasSingleton::Child()) {
+  CamerasChild* child = CamerasSingleton::Child();
+  if (!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;
   }
-  GetCamerasChild()->Shutdown();
+  child->ShutdownAll();
 }
 
 class ShutdownRunnable : public nsRunnable {
 public:
   ShutdownRunnable(RefPtr<nsRunnable> aReplyEvent,
                    nsIThread* aReplyThread)
     : mReplyEvent(aReplyEvent), mReplyThread(aReplyThread) {};
 
@@ -500,35 +501,53 @@ public:
   }
 
 private:
   RefPtr<nsRunnable> mReplyEvent;
   nsIThread* mReplyThread;
 };
 
 void
-CamerasChild::Shutdown()
+CamerasChild::ShutdownAll()
 {
+  // Called with CamerasSingleton::Mutex() held
+  ShutdownParent();
+  ShutdownChild();
+}
+
+void
+CamerasChild::ShutdownParent()
+{
+  // Called with CamerasSingleton::Mutex() held
   {
     MonitorAutoLock monitor(mReplyMonitor);
     mIPCIsAlive = false;
     monitor.NotifyAll();
   }
-
   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();
         return NS_OK;
       });
     CamerasSingleton::Thread()->Dispatch(deleteRunnable, NS_DISPATCH_NORMAL);
+  } else {
+    LOG(("ShutdownParent called without PBackground thread"));
+  }
+}
+
+void
+CamerasChild::ShutdownChild()
+{
+  // Called with CamerasSingleton::Mutex() held
+  if (CamerasSingleton::Thread()) {
     LOG(("PBackground thread exists, dispatching close"));
     // Dispatch closing the IPC thread back to us when the
     // BackgroundChild is closed.
     RefPtr<nsRunnable> event =
       new ThreadDestructor(CamerasSingleton::Thread());
     RefPtr<ShutdownRunnable> runnable =
       new ShutdownRunnable(event, NS_GetCurrentThread());
     CamerasSingleton::Thread()->Dispatch(runnable, NS_DISPATCH_NORMAL);
@@ -602,17 +621,21 @@ CamerasChild::CamerasChild()
 }
 
 CamerasChild::~CamerasChild()
 {
   LOG(("~CamerasChild: %p", this));
 
   {
     OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
-    Shutdown();
+    // In normal circumstances we've already shut down and the
+    // following does nothing. But on fatal IPC errors we will
+    // get destructed immediately, and should not try to reach
+    // the parent.
+    ShutdownChild();
   }
 
   MOZ_COUNT_DTOR(CamerasChild);
 }
 
 webrtc::ExternalRenderer* CamerasChild::Callback(CaptureEngine aCapEngine,
                                                  int capture_id)
 {
--- a/dom/media/systemservices/CamerasChild.h
+++ b/dom/media/systemservices/CamerasChild.h
@@ -187,31 +187,32 @@ public:
                            const char* unique_idUTF8,
                            const unsigned int capability_number,
                            webrtc::CaptureCapability& capability);
   int GetCaptureDevice(CaptureEngine aCapEngine,
                        unsigned int list_number, char* device_nameUTF8,
                        const unsigned int device_nameUTF8Length,
                        char* unique_idUTF8,
                        const unsigned int unique_idUTF8Length);
-  void Shutdown();
+  void ShutdownAll();
 
   webrtc::ExternalRenderer* Callback(CaptureEngine aCapEngine, int capture_id);
-  void AddCallback(const CaptureEngine aCapEngine, const int capture_id,
-                   webrtc::ExternalRenderer* render);
-  void RemoveCallback(const CaptureEngine aCapEngine, const int capture_id);
-
 
 private:
   CamerasChild();
   ~CamerasChild();
   // Dispatch a Runnable to the PCamerasParent, by executing it on the
   // decidecated Cameras IPC/PBackground thread.
   bool DispatchToParent(nsIRunnable* aRunnable,
                         MonitorAutoLock& aMonitor);
+  void AddCallback(const CaptureEngine aCapEngine, const int capture_id,
+                   webrtc::ExternalRenderer* render);
+  void RemoveCallback(const CaptureEngine aCapEngine, const int capture_id);
+  void ShutdownParent();
+  void ShutdownChild();
 
   nsTArray<CapturerElement> mCallbacks;
   // Protects the callback arrays
   Mutex mCallbackMutex;
 
   bool mIPCIsAlive;
 
   // Hold to prevent multiple outstanding requests. We don't use