Bug 1255737 - Backout f31612f8f3bb (Bug 1239873) from beta 48. r=jib, a=lizzard FIREFOX_49_0b4_BUILD1 FIREFOX_49_0b4_RELEASE
authorRandell Jesup <rjesup@jesup.org>
Tue, 22 Mar 2016 01:11:58 -0400
changeset 340302 ab7b68014a1e20c423aa9b50ca76fd8edccb272c
parent 340301 699de62c793d6cd210da769aa50e049a713b908d
child 340303 23af684ebd4c271c3dacd3b724105ebe8f67d681
child 340314 f47eb66b628aacff082cfb76bfe0ca2b660e49b6
push id6294
push userrjesup@wgate.com
push dateMon, 15 Aug 2016 01:43:57 +0000
treeherdermozilla-beta@ab7b68014a1e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjib, lizzard
bugs1255737, 1239873
milestone49.0
Bug 1255737 - Backout f31612f8f3bb (Bug 1239873) from beta 48. r=jib, a=lizzard MozReview-Commit-ID: ADktnfqg6ID
dom/media/MediaStreamGraph.cpp
dom/media/MediaStreamGraphImpl.h
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -18,17 +18,16 @@
 #include "mozilla/Attributes.h"
 #include "TrackUnionStream.h"
 #include "ImageContainer.h"
 #include "AudioCaptureStream.h"
 #include "AudioChannelService.h"
 #include "AudioNodeStream.h"
 #include "AudioNodeExternalInputStream.h"
 #include "mozilla/dom/AudioContextBinding.h"
-#include "mozilla/media/MediaUtils.h"
 #include <algorithm>
 #include "DOMMediaStream.h"
 #include "GeckoProfiler.h"
 #include "mozilla/unused.h"
 #include "mozilla/media/MediaUtils.h"
 #ifdef MOZ_WEBRTC
 #include "AudioOutputObserver.h"
 #endif
@@ -1626,38 +1625,35 @@ MediaStreamGraphImpl::ApplyStreamUpdate(
       stream->mWrapper->NotifyStreamFinished();
     }
 
     stream->NotifyMainThreadListeners();
   }
 }
 
 void
-MediaStreamGraphImpl::ForceShutDown(ShutdownTicket* aShutdownTicket)
+MediaStreamGraphImpl::ForceShutDown()
 {
   NS_ASSERTION(NS_IsMainThread(), "Must be called on main thread");
   STREAM_LOG(LogLevel::Debug, ("MediaStreamGraph %p ForceShutdown", this));
   {
     MonitorAutoLock lock(mMonitor);
     mForceShutDown = true;
-    mForceShutdownTicket = aShutdownTicket;
     if (mLifecycleState == LIFECYCLE_THREAD_NOT_STARTED) {
       // We *could* have just sent this a message to start up, so don't
       // yank the rug out from under it.  Tell it to startup and let it
       // shut down.
       RefPtr<GraphDriver> driver = CurrentDriver();
       MonitorAutoUnlock unlock(mMonitor);
       driver->Start();
     }
     EnsureNextIterationLocked();
   }
 }
 
-/* static */ StaticRefPtr<nsIAsyncShutdownBlocker> gMediaStreamGraphShutdownBlocker;
-
 namespace {
 
 class MediaStreamGraphShutDownRunnable : public Runnable {
 public:
   explicit MediaStreamGraphShutDownRunnable(MediaStreamGraphImpl* aGraph)
     : mGraph(aGraph)
   {}
   NS_IMETHOD Run()
@@ -1676,23 +1672,16 @@ public:
     if (mGraph->mDriver->AsAudioCallbackDriver()) {
       MOZ_ASSERT(!mGraph->mDriver->AsAudioCallbackDriver()->InCallback());
     }
 #endif
 
     mGraph->mDriver->Shutdown(); // This will wait until it's shutdown since
                                  // we'll start tearing down the graph after this
 
-    // We may be one of several graphs. Drop ticket to eventually unblock shutdown.
-    mGraph->mForceShutdownTicket = nullptr;
-
-    // We can't block past the final LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION
-    // stage, since completion of that stage requires all streams to be freed,
-    // which requires shutdown to proceed.
-
     // mGraph's thread is not running so it's OK to do whatever here
     if (mGraph->IsEmpty()) {
       // mGraph is no longer needed, so delete it.
       mGraph->Destroy();
     } else {
       // The graph is not empty.  We must be in a forced shutdown, or a
       // non-realtime graph that has finished processing.  Some later
       // AppendMessage will detect that the manager has been emptied, and
@@ -1749,16 +1738,24 @@ public:
   {
     // Make sure to run this message during shutdown too, to make sure
     // that we balance the number of streams registered with the graph
     // as they're destroyed during shutdown.
     Run();
   }
 };
 
+class MediaStreamGraphShutdownObserver final : public nsIObserver
+{
+  ~MediaStreamGraphShutdownObserver() {}
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+};
+
 } // namespace
 
 void
 MediaStreamGraphImpl::RunInStableState(bool aSourceIsMSG)
 {
   NS_ASSERTION(NS_IsMainThread(), "Must be called on main thread");
 
   nsTArray<nsCOMPtr<nsIRunnable> > runnables;
@@ -3337,58 +3334,49 @@ MediaStreamGraphImpl::Destroy()
 {
   // First unregister from memory reporting.
   UnregisterWeakMemoryReporter(this);
 
   // Clear the self reference which will destroy this instance.
   mSelfRef = nullptr;
 }
 
+NS_IMPL_ISUPPORTS(MediaStreamGraphShutdownObserver, nsIObserver)
+
+static bool gShutdownObserverRegistered = false;
+
+NS_IMETHODIMP
+MediaStreamGraphShutdownObserver::Observe(nsISupports *aSubject,
+                                          const char *aTopic,
+                                          const char16_t *aData)
+{
+  if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
+    for (auto iter = gGraphs.Iter(); !iter.Done(); iter.Next()) {
+      MediaStreamGraphImpl* graph = iter.UserData();
+      graph->ForceShutDown();
+    }
+    nsContentUtils::UnregisterShutdownObserver(this);
+    gShutdownObserverRegistered = false;
+  }
+  return NS_OK;
+}
+
 MediaStreamGraph*
 MediaStreamGraph::GetInstance(MediaStreamGraph::GraphDriverType aGraphDriverRequested,
                               dom::AudioChannel aChannel)
 {
   NS_ASSERTION(NS_IsMainThread(), "Main thread only");
 
   uint32_t channel = static_cast<uint32_t>(aChannel);
   MediaStreamGraphImpl* graph = nullptr;
 
   if (!gGraphs.Get(channel, &graph)) {
-    if (!gMediaStreamGraphShutdownBlocker) {
-
-      class Blocker : public media::ShutdownBlocker
-      {
-      public:
-        Blocker()
-        : media::ShutdownBlocker(NS_LITERAL_STRING(
-            "MediaStreamGraph shutdown: blocking on msg thread")) {}
-
-        NS_IMETHOD
-        BlockShutdown(nsIAsyncShutdownClient* aProfileBeforeChange) override
-        {
-          // Distribute the global async shutdown blocker in a ticket. If there
-          // are zero graphs then shutdown is unblocked when we go out of scope.
-          RefPtr<MediaStreamGraphImpl::ShutdownTicket> ticket =
-              new MediaStreamGraphImpl::ShutdownTicket(gMediaStreamGraphShutdownBlocker.get());
-          gMediaStreamGraphShutdownBlocker = nullptr;
-
-          for (auto iter = gGraphs.Iter(); !iter.Done(); iter.Next()) {
-            iter.UserData()->ForceShutDown(ticket);
-          }
-          return NS_OK;
-        }
-      };
-
-      gMediaStreamGraphShutdownBlocker = new Blocker();
-      nsCOMPtr<nsIAsyncShutdownClient> barrier = MediaStreamGraphImpl::GetShutdownBarrier();
-      nsresult rv = barrier->
-          AddBlocker(gMediaStreamGraphShutdownBlocker,
-                     NS_LITERAL_STRING(__FILE__), __LINE__,
-                     NS_LITERAL_STRING("MediaStreamGraph shutdown"));
-      MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
+    if (!gShutdownObserverRegistered) {
+      gShutdownObserverRegistered = true;
+      nsContentUtils::RegisterShutdownObserver(new MediaStreamGraphShutdownObserver());
     }
 
     CubebUtils::InitPreferredSampleRate();
 
     graph = new MediaStreamGraphImpl(aGraphDriverRequested,
                                      CubebUtils::PreferredSampleRate(),
                                      aChannel);
 
@@ -3426,17 +3414,17 @@ MediaStreamGraph::DestroyNonRealtimeInst
   MediaStreamGraphImpl* graph = static_cast<MediaStreamGraphImpl*>(aGraph);
   if (graph->mForceShutDown)
     return; // already done
 
   if (!graph->mNonRealtimeProcessing) {
     // Start the graph, but don't produce anything
     graph->StartNonRealtimeProcessing(0);
   }
-  graph->ForceShutDown(nullptr);
+  graph->ForceShutDown();
 }
 
 NS_IMPL_ISUPPORTS(MediaStreamGraphImpl, nsIMemoryReporter)
 
 struct ArrayClearer
 {
   explicit ArrayClearer(nsTArray<AudioNodeSizes>& aArray) : mArray(aArray) {}
   ~ArrayClearer() { mArray.Clear(); }
--- a/dom/media/MediaStreamGraphImpl.h
+++ b/dom/media/MediaStreamGraphImpl.h
@@ -10,17 +10,16 @@
 
 #include "nsDataHashtable.h"
 
 #include "mozilla/Monitor.h"
 #include "mozilla/TimeStamp.h"
 #include "nsIMemoryReporter.h"
 #include "nsIThread.h"
 #include "nsIRunnable.h"
-#include "nsIAsyncShutdown.h"
 #include "Latency.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/WeakPtr.h"
 #include "GraphDriver.h"
 #include "AudioMixer.h"
 
 namespace mozilla {
 
@@ -140,58 +139,23 @@ public:
    */
   void ApplyStreamUpdate(StreamUpdate* aUpdate);
   /**
    * Append a ControlMessage to the message queue. This queue is drained
    * during RunInStableState; the messages will run on the graph thread.
    */
   void AppendMessage(UniquePtr<ControlMessage> aMessage);
 
-  // Shutdown helpers.
-
-  static already_AddRefed<nsIAsyncShutdownClient>
-  GetShutdownBarrier()
-  {
-    nsCOMPtr<nsIAsyncShutdownService> svc = services::GetAsyncShutdown();
-    MOZ_RELEASE_ASSERT(svc);
-
-    nsCOMPtr<nsIAsyncShutdownClient> barrier;
-    nsresult rv = svc->GetProfileBeforeChange(getter_AddRefs(barrier));
-    if (!barrier) {
-      // We are probably in a content process. We need to do cleanup at
-      // XPCOM shutdown in leakchecking builds.
-      rv = svc->GetXpcomWillShutdown(getter_AddRefs(barrier));
-    }
-    MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
-    MOZ_RELEASE_ASSERT(barrier);
-    return barrier.forget();
-  }
-
-  class ShutdownTicket final
-  {
-  public:
-    explicit ShutdownTicket(nsIAsyncShutdownBlocker* aBlocker) : mBlocker(aBlocker) {}
-    NS_INLINE_DECL_REFCOUNTING(ShutdownTicket)
-  private:
-    ~ShutdownTicket()
-    {
-      nsCOMPtr<nsIAsyncShutdownClient> barrier = GetShutdownBarrier();
-      barrier->RemoveBlocker(mBlocker);
-    }
-
-    nsCOMPtr<nsIAsyncShutdownBlocker> mBlocker;
-  };
-
   /**
    * Make this MediaStreamGraph enter forced-shutdown state. This state
    * will be noticed by the media graph thread, which will shut down all streams
    * and other state controlled by the media graph thread.
    * This is called during application shutdown.
    */
-  void ForceShutDown(ShutdownTicket* aShutdownTicket);
+  void ForceShutDown();
 
   /**
    * Called before the thread runs.
    */
   void Init();
   // The following methods run on the graph thread (or possibly the main thread if
   // mLifecycleState > LIFECYCLE_RUNNING)
   void AssertOnGraphThreadOrNotRunning() const
@@ -748,22 +712,16 @@ public:
    * The graph should stop processing at or after this time.
    */
   GraphTime mEndTime;
 
   /**
    * True when we need to do a forced shutdown during application shutdown.
    */
   bool mForceShutDown;
-
-  /**
-   * Drop this reference during shutdown to unblock shutdown.
-   **/
-  RefPtr<ShutdownTicket> mForceShutdownTicket;
-
   /**
    * True when we have posted an event to the main thread to run
    * RunInStableState() and the event hasn't run yet.
    */
   bool mPostedRunInStableStateEvent;
 
   // Main thread only