Bug 1273136: Don't leak runnables needed to cleanup gUM streams r=drno
authorRandell Jesup <rjesup@jesup.org>
Fri, 03 Jun 2016 02:39:23 -0400
changeset 341432 0cb38314f603d6a3f01fd90ee296b11df262b0cf
parent 341431 1b3eddbebb7ab27b07d3ff9d90eca37ccb6863a0
child 341433 25c1b11a4c39716ac1baef4373a9851a21a5eb6d
push id1183
push userraliiev@mozilla.com
push dateMon, 05 Sep 2016 20:01:49 +0000
treeherdermozilla-release@3148731bed45 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdrno
bugs1273136
milestone49.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 1273136: Don't leak runnables needed to cleanup gUM streams r=drno MozReview-Commit-ID: BqUMC2jpahM
dom/media/MediaManager.h
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -124,16 +124,17 @@ public:
 class GetUserMediaCallbackMediaStreamListener : public MediaStreamListener
 {
 public:
   // Create in an inactive state
   GetUserMediaCallbackMediaStreamListener(base::Thread *aThread,
     uint64_t aWindowID,
     const PrincipalHandle& aPrincipalHandle)
     : mMediaThread(aThread)
+    , mMainThreadCheck(nullptr)
     , mWindowID(aWindowID)
     , mPrincipalHandle(aPrincipalHandle)
     , mStopped(false)
     , mFinished(false)
     , mRemoved(false)
     , mAudioStopped(false)
     , mVideoStopped(false) {}
 
@@ -144,16 +145,17 @@ public:
     // refcounts.
   }
 
   void Activate(already_AddRefed<SourceMediaStream> aStream,
                 AudioDevice* aAudioDevice,
                 VideoDevice* aVideoDevice)
   {
     MOZ_ASSERT(NS_IsMainThread());
+    mMainThreadCheck = PR_GetCurrentThread();
     mStream = aStream;
     mAudioDevice = aAudioDevice;
     mVideoDevice = aVideoDevice;
 
     mStream->AddListener(this);
   }
 
   MediaStream *Stream() // Can be used to test if Activate was called
@@ -269,24 +271,43 @@ public:
                                             aDesiredTime, mPrincipalHandle);
     }
   }
 
   void
   NotifyEvent(MediaStreamGraph* aGraph,
               MediaStreamListener::MediaStreamGraphEvent aEvent) override
   {
+    nsresult rv;
+    nsCOMPtr<nsIThread> thread;
+
     switch (aEvent) {
       case EVENT_FINISHED:
-        NS_DispatchToMainThread(
-          NewRunnableMethod(this, &GetUserMediaCallbackMediaStreamListener::NotifyFinished));
+        rv = NS_GetMainThread(getter_AddRefs(thread));
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          NS_ASSERTION(false, "Mainthread not available; running on current thread");
+          // Ensure this really *was* MainThread (NS_GetCurrentThread won't work)
+          MOZ_RELEASE_ASSERT(mMainThreadCheck == PR_GetCurrentThread());
+          NotifyFinished();
+          return;
+        }
+        thread->Dispatch(NewRunnableMethod(this, &GetUserMediaCallbackMediaStreamListener::NotifyFinished),
+                         NS_DISPATCH_NORMAL);
         break;
       case EVENT_REMOVED:
-        NS_DispatchToMainThread(
-          NewRunnableMethod(this, &GetUserMediaCallbackMediaStreamListener::NotifyRemoved));
+        rv = NS_GetMainThread(getter_AddRefs(thread));
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          NS_ASSERTION(false, "Mainthread not available; running on current thread");
+          // Ensure this really *was* MainThread (NS_GetCurrentThread won't work)
+          MOZ_RELEASE_ASSERT(mMainThreadCheck == PR_GetCurrentThread());
+          NotifyRemoved();
+          return;
+        }
+        thread->Dispatch(NewRunnableMethod(this, &GetUserMediaCallbackMediaStreamListener::NotifyRemoved),
+                         NS_DISPATCH_NORMAL);
         break;
       case EVENT_HAS_DIRECT_LISTENERS:
         NotifyDirectListeners(aGraph, true);
         break;
       case EVENT_HAS_NO_DIRECT_LISTENERS:
         NotifyDirectListeners(aGraph, false);
         break;
       default:
@@ -303,16 +324,19 @@ public:
   void
   NotifyDirectListeners(MediaStreamGraph* aGraph, bool aHasListeners);
 
   PrincipalHandle GetPrincipalHandle() const { return mPrincipalHandle; }
 
 private:
   // Set at construction
   base::Thread* mMediaThread;
+  // never ever indirect off this; just for assertions
+  PRThread* mMainThreadCheck;
+
   uint64_t mWindowID;
   const PrincipalHandle mPrincipalHandle;
 
   // true after this listener has sent MEDIA_STOP. MainThread only.
   bool mStopped;
 
   // true after the stream this listener is listening to has finished in the
   // MediaStreamGraph. MainThread only.