зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1764119 - Part 1: Do final KillClearOnShutdown after XPCOM threads shutdown, r=xpcom-reviewers,kmag,jstutte
This patch moves where we perform the final KillClearOnShutdown to occur after we've shut down non-main threads, but before the main thread stops accepting events. This should help ensure that unsuspecting events, including those triggered from nsIThreadShutdownTask tasks, don't run after KillClearOnShutdown has been run on background or main threads. This KillClearOnShutdown was moved to occur before nsThreadManager::Shutdown() in bug 1637890, as there were examples of KillClearOnShutdown callbacks which needed to be able to dispatch main-thread runnables. This change should not regress that use-case, as we are still accepting new events on the main thread after the callback. Non-main threads were already unreliable after this call as we already block normal dispatches by setting gXPCOMThreadsShutdown, and new threads cannot be started for the background thread pool. Differential Revision: https://phabricator.services.mozilla.com/D144591
This commit is contained in:
Родитель
80ec444c16
Коммит
73061fa43e
|
@ -648,6 +648,11 @@ nsresult ShutdownXPCOM(nsIServiceManager* aServMgr) {
|
|||
mozilla::KillClearOnShutdown(ShutdownPhase::XPCOMShutdownLoaders);
|
||||
// XXX: Why don't we try a MaybeFastShutdown for XPCOMShutdownLoaders ?
|
||||
|
||||
// Shutdown all remaining threads. This method does not return until
|
||||
// all threads created using the thread manager (with the exception of
|
||||
// the main thread) have exited.
|
||||
nsThreadManager::get().ShutdownNonMainThreads();
|
||||
|
||||
RefPtr<nsObserverService> observerService;
|
||||
CallGetService("@mozilla.org/observer-service;1",
|
||||
(nsObserverService**)getter_AddRefs(observerService));
|
||||
|
@ -660,15 +665,11 @@ nsresult ShutdownXPCOM(nsIServiceManager* aServMgr) {
|
|||
// observers themselves might call ClearOnShutdown().
|
||||
// Some destructors may fire extra runnables that will be processed below.
|
||||
mozilla::KillClearOnShutdown(ShutdownPhase::XPCOMShutdownFinal);
|
||||
|
||||
// Shutdown all remaining threads. This method does not return until
|
||||
// all threads created using the thread manager (with the exception of
|
||||
// the main thread) have exited.
|
||||
nsThreadManager::get().Shutdown();
|
||||
|
||||
// Process our last round of events, and then mark that we've finished main
|
||||
// thread event processing.
|
||||
NS_ProcessPendingEvents(thread);
|
||||
|
||||
// Shutdown the main thread, processing our last round of events, and then
|
||||
// mark that we've finished main thread event processing.
|
||||
nsThreadManager::get().ShutdownMainThread();
|
||||
gXPCOMMainThreadEventsAreDoomed = true;
|
||||
|
||||
BackgroundHangMonitor().NotifyActivity();
|
||||
|
|
|
@ -339,7 +339,7 @@ nsresult nsThreadManager::Init() {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsThreadManager::Shutdown() {
|
||||
void nsThreadManager::ShutdownNonMainThreads() {
|
||||
MOZ_ASSERT(NS_IsMainThread(), "shutdown not called from main thread");
|
||||
|
||||
// Prevent further access to the thread manager (no more new threads!)
|
||||
|
@ -378,8 +378,8 @@ void nsThreadManager::Shutdown() {
|
|||
mMainThread);
|
||||
|
||||
{
|
||||
// We gather the threads from the hashtable into a list, so that we avoid
|
||||
// holding the enumerator lock while calling nsIThread::Shutdown.
|
||||
// We gather the threads into a list, so that we avoid holding the
|
||||
// enumerator lock while calling nsIThread::Shutdown.
|
||||
nsTArray<RefPtr<nsThread>> threadsToShutdown;
|
||||
for (auto* thread : nsThread::Enumerate()) {
|
||||
if (thread->ShutdownRequired()) {
|
||||
|
@ -408,10 +408,23 @@ void nsThreadManager::Shutdown() {
|
|||
// in-flight asynchronous thread shutdowns to complete.
|
||||
mMainThread->WaitForAllAsynchronousShutdowns();
|
||||
|
||||
// In case there are any more events somehow...
|
||||
NS_ProcessPendingEvents(mMainThread);
|
||||
|
||||
// There are no more background threads at this point.
|
||||
}
|
||||
|
||||
void nsThreadManager::ShutdownMainThread() {
|
||||
MOZ_ASSERT(!mInitialized, "Must have called BeginShutdown");
|
||||
|
||||
// Do NS_ProcessPendingEvents but with special handling to set
|
||||
// mEventsAreDoomed atomically with the removal of the last event. This means
|
||||
// that PutEvent cannot succeed if the event would be left in the main thread
|
||||
// queue after our final call to NS_ProcessPendingEvents.
|
||||
// See comments in `nsThread::ThreadFunc` for a more detailed explanation.
|
||||
while (true) {
|
||||
if (mMainThread->mEvents->ShutdownIfNoPendingEvents()) {
|
||||
break;
|
||||
}
|
||||
NS_ProcessPendingEvents(mMainThread);
|
||||
}
|
||||
|
||||
// Normally thread shutdown clears the observer for the thread, but since the
|
||||
// main thread is special we do it manually here after we're sure all events
|
||||
|
|
|
@ -32,9 +32,13 @@ class nsThreadManager : public nsIThreadManager {
|
|||
|
||||
nsresult Init();
|
||||
|
||||
// Shutdown all threads. This function should only be called on the main
|
||||
// thread of the application process.
|
||||
void Shutdown();
|
||||
// Shutdown all threads other than the main thread. This function should only
|
||||
// be called on the main thread of the application process.
|
||||
void ShutdownNonMainThreads();
|
||||
|
||||
// Finish shutting down all threads. This function must be called after
|
||||
// ShutdownNonMainThreads and will take the main thread out of commission.
|
||||
void ShutdownMainThread();
|
||||
|
||||
// Called by nsThread to inform the ThreadManager it exists. This method
|
||||
// must be called when the given thread is the current thread.
|
||||
|
|
Загрузка…
Ссылка в новой задаче