Bug 829907: release video capture device on MainThread (mac only) r=bsmedberg a=akeybl
authorRandell Jesup <rjesup@jesup.org>
Thu, 14 Feb 2013 14:59:27 -0500
changeset 127533 a581fbd356de0437d7a431b1f85752e985a677c2
parent 127532 f75a527a8c4a16eb43e11e895c623b8548fb192b
child 127534 d0a1f24eef41392d5936c47da937a8f926b2203e
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg, akeybl
bugs829907
milestone20.0a2
Bug 829907: release video capture device on MainThread (mac only) r=bsmedberg a=akeybl
content/media/webrtc/MediaEngineWebRTCVideo.cpp
dom/media/MediaManager.h
media/mtransport/build/Makefile.in
--- a/content/media/webrtc/MediaEngineWebRTCVideo.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCVideo.cpp
@@ -1,16 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MediaEngineWebRTC.h"
 #include "Layers.h"
 #include "ImageTypes.h"
 #include "ImageContainer.h"
+#include "mtransport/runnable_utils.h"
 
 namespace mozilla {
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* GetMediaManagerLog();
 #define LOG(msg) PR_LOG(GetMediaManagerLog(), PR_LOG_DEBUG, msg)
 #define LOGFRAME(msg) PR_LOG(GetMediaManagerLog(), 6, msg)
 #else
@@ -222,17 +223,36 @@ nsresult
 MediaEngineWebRTCVideoSource::Deallocate()
 {
   LOG((__FUNCTION__));
   if (mSources.IsEmpty()) {
     if (mState != kStopped && mState != kAllocated) {
       return NS_ERROR_FAILURE;
     }
 
+#ifdef XP_MACOSX
+    // Bug 829907 - on mac, in shutdown, the mainthread stops processing
+    // 'native' events, and the QTKit code uses events to the main native CFRunLoop
+    // in order to provide thread safety.  In order to avoid this locking us up,
+    // release the ViE capture device synchronously on MainThread (so the native
+    // event isn't needed).
+    // XXX Note if MainThread Dispatch()es NS_DISPATCH_SYNC to us we can deadlock.
+    // XXX It might be nice to only do this if we're in shutdown...  Hard to be
+    // sure when that is though.
+    // Thread safety: a) we call this synchronously, and don't use ViECapture from
+    // another thread anywhere else, b) ViEInputManager::DestroyCaptureDevice() grabs
+    // an exclusive object lock and deletes it in a critical section, so all in all
+    // this should be safe threadwise.
+    NS_DispatchToMainThread(WrapRunnable(mViECapture,
+                                         &webrtc::ViECapture::ReleaseCaptureDevice,
+                                         mCaptureIndex),
+                            NS_DISPATCH_SYNC);
+#else
     mViECapture->ReleaseCaptureDevice(mCaptureIndex);
+#endif
     mState = kReleased;
     LOG(("Video device %d deallocated", mCaptureIndex));
   } else {
     LOG(("Video device %d deallocated but still in use", mCaptureIndex));
   }
   return NS_OK;
 }
 
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -309,16 +309,19 @@ private:
 };
 
 class MediaManager MOZ_FINAL : public nsIMediaManagerService,
                                public nsIObserver
 {
 public:
   static already_AddRefed<MediaManager> GetInstance();
 
+  // NOTE: never Dispatch(....,NS_DISPATCH_SYNC) to the MediaManager
+  // thread from the MainThread, as we NS_DISPATCH_SYNC to MainThread
+  // from MediaManager thread.
   static MediaManager* Get() {
     if (!sSingleton) {
       sSingleton = new MediaManager();
 
       NS_NewThread(getter_AddRefs(sSingleton->mMediaThread));
       MM_LOG(("New Media thread for gum"));
 
       NS_ASSERTION(NS_IsMainThread(), "Only create MediaManager on main thread");
--- a/media/mtransport/build/Makefile.in
+++ b/media/mtransport/build/Makefile.in
@@ -32,16 +32,17 @@ EXPORTS_mtransport = \
   ../transportlayer.h \
   ../transportlayerdtls.h \
   ../transportlayerice.h \
   ../transportlayerlog.h \
   ../transportlayerloopback.h \
   ../transportlayerprsock.h \
   ../m_cpp_utils.h \
   ../runnable_utils.h \
+  ../runnable_utils_generated.h \
   ../sigslot.h \
   $(NULL)
 
 CPPSRCS = \
 	$(MTRANSPORT_LCPPSRCS) \
 	$(NULL)
 
 include $(srcdir)/../objs.mk