Bug 1218799: Shutdown MediaManager engines from the MediaManager thread r=jib

This commit is contained in:
Randell Jesup 2015-11-18 15:03:13 -05:00
parent e7ce0828a2
commit c45f35255b
2 changed files with 14 additions and 22 deletions

View File

@ -1478,7 +1478,6 @@ MediaManager::EnumerateRawDevices(uint64_t aWindowId,
MediaManager::MediaManager()
: mMediaThread(nullptr)
, mMutex("mozilla::MediaManager")
, mBackend(nullptr) {
mPrefs.mFreq = 1000; // 1KHz test tone
mPrefs.mWidth = 0; // adaptive default
@ -2400,10 +2399,10 @@ MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
MediaEngine*
MediaManager::GetBackend(uint64_t aWindowId)
{
MOZ_ASSERT(MediaManager::IsInMediaThread());
// Plugin backends as appropriate. The default engine also currently
// includes picture support for Android.
// This IS called off main-thread.
MutexAutoLock lock(mMutex);
if (!mBackend) {
MOZ_RELEASE_ASSERT(!sInShutdown); // we should never create a new backend in shutdown
#if defined(MOZ_WEBRTC)
@ -2600,12 +2599,6 @@ MediaManager::Shutdown()
GetActiveWindows()->Clear();
mActiveCallbacks.Clear();
mCallIds.Clear();
{
MutexAutoLock lock(mMutex);
if (mBackend) {
mBackend->Shutdown(); // ok to invoke multiple times
}
}
// Because mMediaThread is not an nsThread, we must dispatch to it so it can
// clean up BackgroundChild. Continue stopping thread once this is done.
@ -2613,26 +2606,32 @@ MediaManager::Shutdown()
class ShutdownTask : public Task
{
public:
ShutdownTask(already_AddRefed<MediaEngine> aBackend,
ShutdownTask(MediaManager* aManager,
nsRunnable* aReply)
: mReply(aReply)
, mBackend(aBackend) {}
: mManager(aManager)
, mReply(aReply) {}
private:
virtual void
Run()
{
LOG(("MediaManager Thread Shutdown"));
MOZ_ASSERT(MediaManager::IsInMediaThread());
// Must shutdown backend on MediaManager thread, since that's where we started it from!
{
if (mManager->mBackend) {
mManager->mBackend->Shutdown(); // ok to invoke multiple times
}
}
mozilla::ipc::BackgroundChild::CloseForCurrentThread();
// must explicitly do this before dispatching the reply, since the reply may kill us with Stop()
mBackend = nullptr; // last reference, will invoke Shutdown() again
mManager->mBackend = nullptr; // last reference, will invoke Shutdown() again
if (NS_FAILED(NS_DispatchToMainThread(mReply.forget()))) {
LOG(("Will leak thread: DispatchToMainthread of reply runnable failed in MediaManager shutdown"));
}
}
RefPtr<MediaManager> mManager;
RefPtr<nsRunnable> mReply;
RefPtr<MediaEngine> mBackend;
};
// Post ShutdownTask to execute on mMediaThread and pass in a lambda
@ -2645,14 +2644,8 @@ MediaManager::Shutdown()
// note that this == sSingleton
RefPtr<MediaManager> that(sSingleton);
// Release the backend (and call Shutdown()) from within the MediaManager thread
RefPtr<MediaEngine> temp;
{
MutexAutoLock lock(mMutex);
temp = mBackend.forget();
}
// Don't use MediaManager::PostTask() because we're sInShutdown=true here!
mMediaThread->message_loop()->PostTask(FROM_HERE, new ShutdownTask(
temp.forget(),
mMediaThread->message_loop()->PostTask(FROM_HERE, new ShutdownTask(this,
media::NewRunnableFrom([this, that]() mutable {
LOG(("MediaManager shutdown lambda running, releasing MediaManager singleton and thread"));
if (mMediaThread) {

View File

@ -533,8 +533,7 @@ private:
nsAutoPtr<base::Thread> mMediaThread;
nsCOMPtr<nsIAsyncShutdownBlocker> mShutdownBlocker;
Mutex mMutex;
// protected with mMutex:
// ONLY accessed from MediaManagerThread
RefPtr<MediaEngine> mBackend;
static StaticRefPtr<MediaManager> sSingleton;