Bug 888347: Block worker creation at xpcom-shutdown. r=bent

This commit is contained in:
Kyle Huey 2013-09-09 10:54:05 -07:00
parent 17af62bf6e
commit 9b0ed3c6d4
2 changed files with 54 additions and 26 deletions

View File

@ -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<nsIObserverService> 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<WorkerPrivate*, 100> 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<nsIObserverService> 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;

View File

@ -208,6 +208,9 @@ private:
nsresult
Init();
void
Shutdown();
void
Cleanup();