author | Stephen A Pohl <spohl.mozilla.bugs@gmail.com> |
Wed, 21 Mar 2018 19:22:57 -0400 | |
changeset 409412 | ff30955a00d2f6cbba9288b3ba2b7b749a577628 |
parent 409411 | 9185d9c69f0ed9ccc1a1d5eacf5beb8df38af060 |
child 409413 | 17c6a17df94a52888a467a1e23d939174e21c37b |
push id | 33687 |
push user | apavel@mozilla.com |
push date | Thu, 22 Mar 2018 09:31:48 +0000 |
treeherder | mozilla-central@7771df14ea18 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jimm |
bugs | 1423261 |
milestone | 61.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
dom/ipc/ContentChild.cpp | file | annotate | diff | comparison | revisions | |
dom/ipc/ContentChild.h | file | annotate | diff | comparison | revisions |
--- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -539,30 +539,37 @@ StaticAutoPtr<ContentChild::ShutdownCana ContentChild::ContentChild() : mID(uint64_t(-1)) #if defined(XP_WIN) && defined(ACCESSIBILITY) , mMainChromeTid(0) , mMsaaID(0) #endif , mIsAlive(true) , mShuttingDown(false) + , mShutdownTimeout(0) { // This process is a content process, so it's clearly running in // multiprocess mode! nsDebugImpl::SetMultiprocessMode("Child"); // When ContentChild is created, the observer service does not even exist. // When ContentChild::RecvSetXPCOMProcessAttributes is called (the first // IPDL call made on this object), shutdown may have already happened. Thus // we create a canary here that relies upon getting cleared if shutdown // happens without requiring the observer service at this time. if (!sShutdownCanary) { sShutdownCanary = new ShutdownCanary(); ClearOnShutdown(&sShutdownCanary, ShutdownPhase::Shutdown); } + // If a shutdown message is received from within a nested event loop, we set + // the timeout for the nested event loop to half the ForceKillTimer timeout + // (in ms) to leave enough time to send the FinishShutdown message to the + // parent. + mShutdownTimeout = + Preferences::GetInt("dom.ipc.tabs.shutdownTimeoutSecs", 5) * 1000 / 2; } #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4722) /* Silence "destructor never returns" warning */ #endif ContentChild::~ContentChild() @@ -3025,38 +3032,42 @@ ContentChild::RecvShutdown() ShutdownInternal(); return IPC_OK(); } void ContentChild::ShutdownInternal() { + CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("IPCShutdownState"), + NS_LITERAL_CSTRING("RecvShutdown")); + // If we receive the shutdown message from within a nested event loop, we want // to wait for that event loop to finish. Otherwise we could prematurely // terminate an "unload" or "pagehide" event handler (which might be doing a - // sync XHR, for example). - CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("IPCShutdownState"), - NS_LITERAL_CSTRING("RecvShutdown")); - - MOZ_ASSERT(NS_IsMainThread()); - RefPtr<nsThread> mainThread = nsThreadManager::get().GetCurrentThread(); + // sync XHR, for example). However, we need to strike a balance and shut down + // within a reasonable amount of time (mShutdownTimeout) or the ForceKillTimer + // in the parent will execute and kill us hard. // Note that we only have to check the recursion count for the current // cooperative thread. Since the Shutdown message is not labeled with a // SchedulerGroup, there can be no other cooperative threads doing work while // we're running. - if (mainThread && mainThread->RecursionDepth() > 1) { + MOZ_ASSERT(NS_IsMainThread()); + RefPtr<nsThread> mainThread = nsThreadManager::get().GetCurrentThread(); + if (mainThread && mainThread->RecursionDepth() > 1 && mShutdownTimeout > 0) { // We're in a nested event loop. Let's delay for an arbitrary period of // time (100ms) in the hopes that the event loop will have finished by // then. + int32_t delay = 100; MessageLoop::current()->PostDelayedTask( NewRunnableMethod( "dom::ContentChild::RecvShutdown", this, &ContentChild::ShutdownInternal), - 100); + delay); + mShutdownTimeout -= delay; return; } mShuttingDown = true; #ifdef NIGHTLY_BUILD HangMonitor::UnregisterAnnotator(PendingInputEventHangAnnotator::sSingleton); #endif
--- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -823,16 +823,17 @@ private: // Hashtable to keep track of the pending file creation. // These items are removed when RecvFileCreationResponse is received. nsRefPtrHashtable<nsIDHashKey, FileCreatorHelper> mFileCreationPending; nsClassHashtable<nsUint64HashKey, AnonymousTemporaryFileCallback> mPendingAnonymousTemporaryFiles; mozilla::Atomic<bool> mShuttingDown; + int32_t mShutdownTimeout; #ifdef NIGHTLY_BUILD // NOTE: This member is atomic because it can be accessed from off-main-thread. mozilla::Atomic<uint32_t> mPendingInputEvents; #endif DISALLOW_EVIL_CONSTRUCTORS(ContentChild); };