diff --git a/content/media/MediaStreamGraph.cpp b/content/media/MediaStreamGraph.cpp index 9f48420295b1..c2fa9751a39b 100644 --- a/content/media/MediaStreamGraph.cpp +++ b/content/media/MediaStreamGraph.cpp @@ -1413,6 +1413,10 @@ MediaStreamGraphImpl::RunInStableState() NS_ASSERTION(NS_IsMainThread(), "Must be called on main thread"); nsTArray > runnables; + // When we're doing a forced shutdown, pending control messages may be + // run on the main thread via RunDuringShutdown. Those messages must + // run without the graph monitor being held. So, we collect them here. + nsTArray > controlMessagesToRunDuringShutdown; { MonitorAutoLock lock(mMonitor); @@ -1428,17 +1432,13 @@ MediaStreamGraphImpl::RunInStableState() mStreamUpdates.Clear(); if (mLifecycleState == LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP && mForceShutDown) { + // Defer calls to RunDuringShutdown() to happen while mMonitor is not held. for (PRUint32 i = 0; i < mMessageQueue.Length(); ++i) { MessageBlock& mb = mMessageQueue[i]; - for (PRUint32 j = 0; j < mb.mMessages.Length(); ++j) { - mb.mMessages[j]->RunDuringShutdown(); - } + controlMessagesToRunDuringShutdown.MoveElementsFrom(mb.mMessages); } mMessageQueue.Clear(); - for (PRUint32 i = 0; i < mCurrentTaskMessageQueue.Length(); ++i) { - mCurrentTaskMessageQueue[i]->RunDuringShutdown(); - } - mCurrentTaskMessageQueue.Clear(); + controlMessagesToRunDuringShutdown.MoveElementsFrom(mCurrentTaskMessageQueue); // Stop MediaStreamGraph threads. Do not clear gGraph since // we have outstanding DOM objects that may need it. mLifecycleState = LIFECYCLE_WAITING_FOR_THREAD_SHUTDOWN; @@ -1497,6 +1497,9 @@ MediaStreamGraphImpl::RunInStableState() for (PRUint32 i = 0; i < runnables.Length(); ++i) { runnables[i]->Run(); } + for (PRUint32 i = 0; i < controlMessagesToRunDuringShutdown.Length(); ++i) { + controlMessagesToRunDuringShutdown[i]->RunDuringShutdown(); + } } static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);