Bug 1183482: Fix shutdown hang. r=cpearce
authorJean-Yves Avenard <jyavenard@mozilla.com>
Tue, 14 Jul 2015 13:12:29 +1000
changeset 253136 e988de526f82dc4209655f1202de3f7dc732768a
parent 253135 ef1250ce23a38f97b3f75308ef9366319938b4fa
child 253137 798e3c758a62be0958dc5574617fd27b402720f7
push id29061
push userryanvm@gmail.com
push dateThu, 16 Jul 2015 18:53:45 +0000
treeherdermozilla-central@a0f4a688433d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1183482
milestone42.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 1183482: Fix shutdown hang. r=cpearce The MediaFormatReader destructor is only called once all media task queues have shutdown. However, the main thread demuxer always owned a reference to trackbuffer task queue.
dom/media/MediaFormatReader.cpp
dom/media/mediasource/MediaSourceDecoder.cpp
dom/media/mediasource/MediaSourceDemuxer.cpp
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -76,26 +76,16 @@ MediaFormatReader::MediaFormatReader(Abs
 {
   MOZ_ASSERT(aDemuxer);
   MOZ_COUNT_CTOR(MediaFormatReader);
 }
 
 MediaFormatReader::~MediaFormatReader()
 {
   MOZ_COUNT_DTOR(MediaFormatReader);
-  // shutdown main thread demuxer and track demuxers.
-  if (mAudioTrackDemuxer) {
-    mAudioTrackDemuxer->BreakCycles();
-    mAudioTrackDemuxer = nullptr;
-  }
-  if (mVideoTrackDemuxer) {
-    mVideoTrackDemuxer->BreakCycles();
-    mVideoTrackDemuxer = nullptr;
-  }
-  mMainThreadDemuxer = nullptr;
 }
 
 nsRefPtr<ShutdownPromise>
 MediaFormatReader::Shutdown()
 {
   MOZ_ASSERT(OnTaskQueue());
 
   mDemuxerInitRequest.DisconnectIfExists();
@@ -140,16 +130,27 @@ MediaFormatReader::Shutdown()
     mVideo.mTaskQueue->BeginShutdown();
     mVideo.mTaskQueue->AwaitShutdownAndIdle();
     mVideo.mTaskQueue = nullptr;
   }
   MOZ_ASSERT(mVideo.mPromise.IsEmpty());
 
   mDemuxer = nullptr;
 
+  // shutdown main thread demuxer and track demuxers.
+  if (mAudioTrackDemuxer) {
+    mAudioTrackDemuxer->BreakCycles();
+    mAudioTrackDemuxer = nullptr;
+  }
+  if (mVideoTrackDemuxer) {
+    mVideoTrackDemuxer->BreakCycles();
+    mVideoTrackDemuxer = nullptr;
+  }
+  mMainThreadDemuxer = nullptr;
+
   mPlatform = nullptr;
 
   return MediaDecoderReader::Shutdown();
 }
 
 void
 MediaFormatReader::InitLayersBackendType()
 {
@@ -1519,36 +1520,38 @@ MediaFormatReader::NotifyDemuxer(uint32_
 }
 
 void
 MediaFormatReader::NotifyDataArrivedInternal(uint32_t aLength, int64_t aOffset)
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_ASSERT(aLength);
 
-  if (!mInitDone) {
+  if (!mInitDone || mShutdown) {
     return;
   }
 
+  MOZ_ASSERT(mMainThreadDemuxer);
+
   // Queue a task to notify our main thread demuxer.
   nsCOMPtr<nsIRunnable> task =
     NS_NewRunnableMethodWithArgs<uint32_t, int64_t>(
       mMainThreadDemuxer, &MediaDataDemuxer::NotifyDataArrived,
       aLength, aOffset);
   AbstractThread::MainThread()->Dispatch(task.forget());
 
   NotifyDemuxer(aLength, aOffset);
 }
 
 void
 MediaFormatReader::NotifyDataRemoved()
 {
   MOZ_ASSERT(OnTaskQueue());
 
-  if (!mInitDone) {
+  if (!mInitDone || mShutdown) {
     return;
   }
 
   MOZ_ASSERT(mMainThreadDemuxer);
 
   // Queue a task to notify our main thread demuxer.
   nsCOMPtr<nsIRunnable> task =
     NS_NewRunnableMethod(
--- a/dom/media/mediasource/MediaSourceDecoder.cpp
+++ b/dom/media/mediasource/MediaSourceDecoder.cpp
@@ -141,16 +141,17 @@ void
 MediaSourceDecoder::Shutdown()
 {
   MSE_DEBUG("Shutdown");
   // Detach first so that TrackBuffers are unused on the main thread when
   // shut down on the decode task queue.
   if (mMediaSource) {
     mMediaSource->Detach();
   }
+  mDemuxer = nullptr;
 
   MediaDecoder::Shutdown();
   // Kick WaitForData out of its slumber.
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   mon.NotifyAll();
 }
 
 /*static*/
--- a/dom/media/mediasource/MediaSourceDemuxer.cpp
+++ b/dom/media/mediasource/MediaSourceDemuxer.cpp
@@ -309,17 +309,20 @@ MediaSourceTrackDemuxer::GetBuffered()
   return mManager->Buffered();
 }
 
 void
 MediaSourceTrackDemuxer::BreakCycles()
 {
   nsRefPtr<MediaSourceTrackDemuxer> self = this;
   nsCOMPtr<nsIRunnable> task =
-    NS_NewRunnableFunction([self]() { self->mParent = nullptr; } );
+    NS_NewRunnableFunction([self]() {
+      self->mParent = nullptr;
+      self->mManager = nullptr;
+    } );
   mParent->GetTaskQueue()->Dispatch(task.forget());
 }
 
 nsRefPtr<MediaSourceTrackDemuxer::SeekPromise>
 MediaSourceTrackDemuxer::DoSeek(media::TimeUnit aTime)
 {
   if (aTime.ToMicroseconds() && !mBufferedRanges.Contains(aTime)) {
     // We don't have the data to seek to.