From 9b0ed3c6d4d7f175334fa84e191d0e555cd57007 Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Mon, 9 Sep 2013 10:54:05 -0700 Subject: [PATCH] Bug 888347: Block worker creation at xpcom-shutdown. r=bent --- dom/workers/RuntimeService.cpp | 77 ++++++++++++++++++++++------------ dom/workers/RuntimeService.h | 3 ++ 2 files changed, 54 insertions(+), 26 deletions(-) diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index 94ec06923b6b..777727707a55 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -1511,6 +1511,9 @@ RuntimeService::Init() obs->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false); NS_ENSURE_SUCCESS(rv, rv); + rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); + NS_ENSURE_SUCCESS(rv, rv); + mObserved = true; if (NS_FAILED(obs->AddObserver(this, GC_REQUEST_OBSERVER_TOPIC, false))) { @@ -1598,13 +1601,15 @@ RuntimeService::Init() return NS_OK; } -// This spins the event loop until all workers are finished and their threads -// have been joined. void -RuntimeService::Cleanup() +RuntimeService::Shutdown() { AssertIsOnMainThread(); + MOZ_ASSERT(!mShuttingDown); + // That's it, no more workers. + mShuttingDown = true; + nsCOMPtr obs = services::GetObserverService(); NS_WARN_IF_FALSE(obs, "Failed to get observer service?!"); @@ -1614,8 +1619,40 @@ RuntimeService::Cleanup() NS_WARNING("NotifyObservers failed!"); } - // That's it, no more workers. - mShuttingDown = true; + { + MutexAutoLock lock(mMutex); + + nsAutoTArray workers; + mDomainMap.EnumerateRead(AddAllTopLevelWorkersToArray, &workers); + + if (!workers.IsEmpty()) { + + // Cancel all top-level workers. + { + MutexAutoUnlock unlock(mMutex); + + AutoSafeJSContext cx; + JSAutoRequest ar(cx); + + for (uint32_t index = 0; index < workers.Length(); index++) { + if (!workers[index]->Kill(cx)) { + NS_WARNING("Failed to cancel worker!"); + } + } + } + } + } +} + +// This spins the event loop until all workers are finished and their threads +// have been joined. +void +RuntimeService::Cleanup() +{ + AssertIsOnMainThread(); + + nsCOMPtr obs = services::GetObserverService(); + NS_WARN_IF_FALSE(obs, "Failed to get observer service?!"); if (mIdleThreadTimer) { if (NS_FAILED(mIdleThreadTimer->Cancel())) { @@ -1631,24 +1668,8 @@ RuntimeService::Cleanup() mDomainMap.EnumerateRead(AddAllTopLevelWorkersToArray, &workers); if (!workers.IsEmpty()) { - nsIThread* currentThread; - - // Cancel all top-level workers. - { - MutexAutoUnlock unlock(mMutex); - - currentThread = NS_GetCurrentThread(); - NS_ASSERTION(currentThread, "This should never be null!"); - - AutoSafeJSContext cx; - JSAutoRequest ar(cx); - - for (uint32_t index = 0; index < workers.Length(); index++) { - if (!workers[index]->Kill(cx)) { - NS_WARNING("Failed to cancel worker!"); - } - } - } + nsIThread* currentThread = NS_GetCurrentThread(); + NS_ASSERTION(currentThread, "This should never be null!"); // Shut down any idle threads. if (!mIdleThreadArray.IsEmpty()) { @@ -1734,9 +1755,9 @@ RuntimeService::Cleanup() NS_WARNING("Failed to unregister for memory pressure notifications!"); } - nsresult rv = - obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID); - mObserved = NS_FAILED(rv); + obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID); + obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); + mObserved = false; } } @@ -1935,6 +1956,10 @@ RuntimeService::Observe(nsISupports* aSubject, const char* aTopic, { AssertIsOnMainThread(); + if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) { + Shutdown(); + return NS_OK; + } if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID)) { Cleanup(); return NS_OK; diff --git a/dom/workers/RuntimeService.h b/dom/workers/RuntimeService.h index df6adf355600..878b74fc2f5b 100644 --- a/dom/workers/RuntimeService.h +++ b/dom/workers/RuntimeService.h @@ -208,6 +208,9 @@ private: nsresult Init(); + void + Shutdown(); + void Cleanup();