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 300432 0cb38314f603d6a3f01fd90ee296b11df262b0cf
parent 300431 1b3eddbebb7ab27b07d3ff9d90eca37ccb6863a0
child 300433 25c1b11a4c39716ac1baef4373a9851a21a5eb6d
push id19549
push usercbook@mozilla.com
push dateMon, 06 Jun 2016 10:04:12 +0000
treeherderfx-team@7fc6eedd3348 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdrno
bugs1273136
milestone49.0a1
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.