diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 9f828d01a6e..27ccd50eabb 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -2496,11 +2496,10 @@ ContentChild::RecvShutdown() if (os) { os->NotifyObservers(this, "content-child-shutdown", nullptr); } - // Let the parent know we're done and let it close the channel. - // Both sides will clean up even if an error occurs here. - MessageLoop::current()->PostTask( - FROM_HERE, - NewRunnableMethod(this, &ContentChild::SendFinishShutdown)); + + // Ignore errors here. If this fails, the parent will kill us after a + // timeout. + unused << SendFinishShutdown(); return true; } diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 44b15881077..e67b4a3fab7 100755 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -1502,8 +1502,7 @@ ContentParent::ShutDownProcess(ShutDownMethod aMethod) // other methods. We first call Shutdown() in the child. After the child is // ready, it calls FinishShutdown() on us. Then we close the channel. if (aMethod == SEND_SHUTDOWN_MESSAGE) { - - if (SendShutdown()) { + if (mIPCOpen && SendShutdown()) { mShutdownPending = true; } @@ -1776,7 +1775,7 @@ ContentParent::ActorDestroy(ActorDestroyReason why) // Signal shutdown completion regardless of error state, // so we can finish waiting in the xpcom-shutdown observer. - mShutdownComplete = true; + mIPCOpen = false; if (why == NormalShutdown && !mCalledClose) { // If we shut down normally but haven't called Close, assume somebody @@ -2000,7 +1999,7 @@ ContentParent::InitializeMembers() mCalledKillHard = false; mCreatedPairedMinidumps = false; mShutdownPending = false; - mShutdownComplete = false; + mIPCOpen = true; } ContentParent::ContentParent(mozIApplication* aApp, @@ -2745,15 +2744,15 @@ ContentParent::Observe(nsISupports* aSubject, const char16_t* aData) { if (!strcmp(aTopic, "xpcom-shutdown") && mSubprocess) { - if (mShutdownPending) { - // Wait for shutdown to complete, so that we receive any shutdown - // data (e.g. telemetry) from the child before we quit. - while (!mShutdownComplete) { - NS_ProcessNextEvent(nullptr, true); - } - } else { - // Just close the channel if we never tried shutting down. - ShutDownProcess(CLOSE_CHANNEL); + if (!mShutdownPending && mIPCOpen) { + ShutDownProcess(SEND_SHUTDOWN_MESSAGE); + } + + // Wait for shutdown to complete, so that we receive any shutdown + // data (e.g. telemetry) from the child before we quit. + // This loop terminate prematurely based on mForceKillTimer. + while (mIPCOpen) { + NS_ProcessNextEvent(nullptr, true); } NS_ASSERTION(!mSubprocess, "Close should have nulled mSubprocess"); } diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index c5e5b7bb664..6615c8e2f6a 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -813,7 +813,7 @@ private: bool mCalledKillHard; bool mCreatedPairedMinidumps; bool mShutdownPending; - bool mShutdownComplete; + bool mIPCOpen; friend class CrashReporterParent;