mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 1631304 - Reject AbstractThread dispatches after the main thread has ceased event proccessing. r=erahm
Differential Revision: https://phabricator.services.mozilla.com/D72263
This commit is contained in:
parent
a50600019a
commit
d90069e220
@ -148,6 +148,7 @@ nsresult nsLocalFileConstructor(nsISupports* aOuter, const nsIID& aIID,
|
||||
nsComponentManagerImpl* nsComponentManagerImpl::gComponentManager = nullptr;
|
||||
bool gXPCOMShuttingDown = false;
|
||||
bool gXPCOMThreadsShutDown = false;
|
||||
bool gXPCOMMainThreadEventsAreDoomed = false;
|
||||
char16_t* gGREBinPath = nullptr;
|
||||
|
||||
static NS_DEFINE_CID(kINIParserFactoryCID, NS_INIPARSERFACTORY_CID);
|
||||
@ -652,7 +653,10 @@ nsresult ShutdownXPCOM(nsIServiceManager* aServMgr) {
|
||||
// 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);
|
||||
gXPCOMMainThreadEventsAreDoomed = true;
|
||||
|
||||
BackgroundHangMonitor().NotifyActivity();
|
||||
|
||||
|
@ -32,6 +32,7 @@ DECL_CLASS(nsIDebug2);
|
||||
#ifdef __cplusplus
|
||||
extern bool gXPCOMShuttingDown;
|
||||
extern bool gXPCOMThreadsShutDown;
|
||||
extern bool gXPCOMMainThreadEventsAreDoomed;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -47,14 +47,36 @@ class XPCOMThreadWrapper : public AbstractThread {
|
||||
|
||||
nsresult Dispatch(already_AddRefed<nsIRunnable> aRunnable,
|
||||
DispatchReason aReason = NormalDispatch) override {
|
||||
nsCOMPtr<nsIRunnable> r = aRunnable;
|
||||
AbstractThread* currentThread;
|
||||
if (aReason != TailDispatch && (currentThread = GetCurrent()) &&
|
||||
RequiresTailDispatch(currentThread)) {
|
||||
return currentThread->TailDispatcher().AddTask(this,
|
||||
std::move(aRunnable));
|
||||
return currentThread->TailDispatcher().AddTask(this, r.forget());
|
||||
}
|
||||
|
||||
RefPtr<nsIRunnable> runner = new Runner(this, std::move(aRunnable));
|
||||
// At a certain point during shutdown, we stop processing events from the
|
||||
// main thread event queue (this happens long after all _other_ XPCOM
|
||||
// threads have been shut down). However, various bits of subsequent
|
||||
// teardown logic (the media shutdown blocker and the final shutdown cycle
|
||||
// collection) can trigger state watching and state mirroring notifications
|
||||
// that result in dispatch to the main thread. This causes shutdown leaks,
|
||||
// because the |Runner| wrapper below creates a guaranteed cycle
|
||||
// (Thread->EventQueue->Runnable->Thread) until the event is processed. So
|
||||
// if we put the event into a queue that will never be processed, we'll wind
|
||||
// up with a leak.
|
||||
//
|
||||
// We opt to just release the runnable in that case. Ordinarily, this
|
||||
// approach could cause problems for runnables that are only safe to be
|
||||
// released on the target thread (and not the dispatching thread). This is
|
||||
// why XPCOM thread dispatch explicitly leaks the runnable when dispatch
|
||||
// fails, rather than releasing it. But given that this condition only
|
||||
// applies very late in shutdown when only one thread remains operational,
|
||||
// that concern is unlikely to apply.
|
||||
if (gXPCOMMainThreadEventsAreDoomed) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<nsIRunnable> runner = new Runner(this, r.forget());
|
||||
return mThread->Dispatch(runner.forget(), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user