Bug 1208656 - Grab the tail dispatch each time in case the runnable spins the event loop. r=khuey, a=lizzard
authorBobby Holley <bobbyholley@gmail.com>
Fri, 02 Oct 2015 15:42:15 -0700
changeset 296318 982890149ba141b4d8400f0308d1173b3346b5d0
parent 296317 517f693bf0634c74a34ee91e6e580d275407c43e
child 296319 8b99dcd48e694665bfab228e7afd284a272f49fa
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey, lizzard
bugs1208656
milestone43.0a2
Bug 1208656 - Grab the tail dispatch each time in case the runnable spins the event loop. r=khuey, a=lizzard If the runnable spins the event loop, we may end up firing the tail dispatcher, which causes the AutoTaskDispatcher to be destroyed, after which point invoking methods on it will crash. We need to grab it each time so that it will be lazily instantiated as-needed.
dom/media/MediaStreamGraph.cpp
dom/media/tests/mochitest/mochitest.ini
dom/media/tests/mochitest/test_getUserMedia_spinEventLoop.html
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -1492,29 +1492,28 @@ MediaStreamGraphImpl::RunInStableState(b
     controlMessagesToRunDuringShutdown[i]->RunDuringShutdown();
   }
 
 #ifdef DEBUG
   mCanRunMessagesSynchronously = mDetectedNotRunning &&
     mLifecycleState >= LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN;
 #endif
 
-  TaskDispatcher& tailDispatcher = AbstractThread::MainThread()->TailDispatcher();
   for (uint32_t i = 0; i < runnables.Length(); ++i) {
     runnables[i]->Run();
     // "Direct" tail dispatcher are supposed to run immediately following the
     // execution of the current task. So the meta-tasking that we do here in
     // RunInStableState() breaks that abstraction a bit unless we handle it here.
     //
     // This is particularly important because we can end up with a "stream
     // ended" notification immediately following a "stream available" notification,
     // and we need to make sure that the watcher responding to "stream available"
     // has a chance to run before the second notification starts tearing things
     // down.
-    tailDispatcher.DrainDirectTasks();
+    AbstractThread::MainThread()->TailDispatcher().DrainDirectTasks();
   }
 }
 
 
 void
 MediaStreamGraphImpl::EnsureRunInStableState()
 {
   NS_ASSERTION(NS_IsMainThread(), "main thread only");
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -47,16 +47,18 @@ skip-if = buildapp == 'mulet' || buildap
 skip-if = (toolkit == 'gonk' || buildapp == 'mulet' && debug) # debug-only failure, turned an intermittent (bug 962579) into a permanant orange
 [test_getUserMedia_constraints.html]
 [test_getUserMedia_callbacks.html]
 skip-if = toolkit == 'gonk' || buildapp == 'mulet' || buildapp == 'mulet' # Bug 1063290, intermittent timeout # TC: Bug 1144079 - Re-enable Mulet mochitests and reftests taskcluster-specific disables.
 [test_getUserMedia_gumWithinGum.html]
 [test_getUserMedia_playAudioTwice.html]
 [test_getUserMedia_playVideoAudioTwice.html]
 [test_getUserMedia_playVideoTwice.html]
+[test_getUserMedia_spinEventLoop.html]
+skip-if = (toolkit == 'gonk' || buildapp == 'mulet' && debug) # copied from basicAudio
 [test_getUserMedia_stopAudioStream.html]
 [test_getUserMedia_stopAudioStreamWithFollowupAudio.html]
 [test_getUserMedia_stopVideoAudioStream.html]
 [test_getUserMedia_stopVideoAudioStreamWithFollowupVideoAudio.html]
 [test_getUserMedia_stopVideoStream.html]
 [test_getUserMedia_stopVideoStreamWithFollowupVideo.html]
 [test_getUserMedia_peerIdentity.html]
 skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 1021776, too --ing slow on b2g)
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_getUserMedia_spinEventLoop.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <script type="application/javascript" src="mediaStreamPlayback.js"></script>
+</head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+  createHTML({ title: "getUserMedia Basic Audio Test", bug: "1208656" });
+  /**
+   * Run a test to verify that we can spin the event loop from within a mozGUM callback.
+   */
+  runTest(() => {
+    var testAudio = createMediaElement('audio', 'testAudio');
+    return new Promise((resolve, reject) => {
+      navigator.mozGetUserMedia({ audio: true }, () => {
+	var syncXHR = new XMLHttpRequest();
+	syncXHR.open('GET', location, false);
+	syncXHR.send();
+	ok(true, "Didn't crash");
+	resolve();
+      }, () => {});
+    });
+  });
+
+</script>
+</pre>
+</body>
+</html>