diff --git a/xpcom/base/AppShutdown.cpp b/xpcom/base/AppShutdown.cpp index 680739b73c12..5844551095cb 100644 --- a/xpcom/base/AppShutdown.cpp +++ b/xpcom/base/AppShutdown.cpp @@ -340,6 +340,23 @@ void AppShutdown::AdvanceShutdownPhaseInternal( if (sCurrentShutdownPhase >= aPhase) { return; } + + nsCOMPtr thread = do_GetCurrentThread(); + if (sCurrentShutdownPhase >= ShutdownPhase::AppShutdownConfirmed) { + // Give runnables dispatched so far as part of the ongoing phase a chance + // to run before actually advancing the phase. We can do this only after + // we passed the point of no return and thus can expect a linear flow + // through our shutdown phases. This way the processing is also covered + // by the terminator's timer. + // Note that this happens only for main thread runnables, such that the + // correct way of ensuring shutdown processing remains to have an async + // shutdown blocker. + if (thread) { + NS_ProcessPendingEvents(thread); + } + } + + // From now on any IsInOrBeyond checks will find the new phase set. sCurrentShutdownPhase = aPhase; // TODO: Bug 1768581 @@ -371,6 +388,10 @@ void AppShutdown::AdvanceShutdownPhaseInternal( #endif obsService->NotifyObservers(aNotificationSubject, aTopic, aNotificationData); + // Empty our MT event queue again after the notification has finished + if (thread) { + NS_ProcessPendingEvents(thread); + } } } } diff --git a/xpcom/build/XPCOMInit.cpp b/xpcom/build/XPCOMInit.cpp index 7ef9a98abd91..ae2ff7027c22 100644 --- a/xpcom/build/XPCOMInit.cpp +++ b/xpcom/build/XPCOMInit.cpp @@ -585,7 +585,6 @@ nsresult ShutdownXPCOM(nsIServiceManager* aServMgr) { // This must happen after the shutdown of media and widgets, which // are triggered by the NS_XPCOM_SHUTDOWN_OBSERVER_ID notification. - NS_ProcessPendingEvents(thread); gfxPlatform::ShutdownLayersIPC(); mozilla::AppShutdown::AdvanceShutdownPhase( @@ -595,11 +594,11 @@ nsresult ShutdownXPCOM(nsIServiceManager* aServMgr) { // dispatches to non main-thread threads. ThreadEventTarget::XPCOMShutdownThreadsNotificationFinished(); #endif - NS_ProcessPendingEvents(thread); // Shutdown the timer thread and all timers that might still be alive nsTimerImpl::Shutdown(); + // Have an extra round of processing after the timers went away. NS_ProcessPendingEvents(thread); // Shutdown all remaining threads. This method does not return until @@ -617,11 +616,9 @@ nsresult ShutdownXPCOM(nsIServiceManager* aServMgr) { // XPCOMShutdownFinal is the default phase for ClearOnShutdown. // This AdvanceShutdownPhase will thus free most ClearOnShutdown()'ed // smart pointers. Some destructors may fire extra main thread runnables - // that will be processed below. + // that will be processed inside AdvanceShutdownPhase. AppShutdown::AdvanceShutdownPhase(ShutdownPhase::XPCOMShutdownFinal); - 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();