# HG changeset patch # User Stephen A Pohl # Date 1524015502 14400 # Node ID c8842b205236ab4e73ffa1892c00fe379bfd9efd # Parent 5842c8034e4d8fbaf2560c2c2df226d86ef28fa2 Bug 1423261: Skip intentionally crashing the browser during KillHard shutdowns. r=jimm diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -3028,16 +3028,21 @@ ContentParent::KillHard(const char* aRea // process handle becomes invalid on the first call, causing a second call // to crash our process - more details in bug 890840. if (mCalledKillHard) { return; } mCalledKillHard = true; mForceKillTimer = nullptr; + MessageChannel* channel = GetIPCChannel(); + if (channel) { + channel->SetInKillHardShutdown(); + } + // We're about to kill the child process associated with this content. // Something has gone wrong to get us here, so we generate a minidump // of the parent and child for submission to the crash server. if (mCrashReporter) { // GeneratePairedMinidump creates two minidumps for us - the main // one is for the content process we're about to kill, and the other // one is for the main browser process. That second one is the extra // minidump tagging along, so we have to tell the crash reporter that diff --git a/ipc/glue/MessageChannel.cpp b/ipc/glue/MessageChannel.cpp --- a/ipc/glue/MessageChannel.cpp +++ b/ipc/glue/MessageChannel.cpp @@ -529,17 +529,18 @@ MessageChannel::MessageChannel(const cha mRemoteStackDepthGuess(0), mSawInterruptOutMsg(false), mIsWaitingForIncoming(false), mAbortOnError(false), mNotifiedChannelDone(false), mFlags(REQUIRE_DEFAULT), mPeerPidSet(false), mPeerPid(-1), - mIsPostponingSends(false) + mIsPostponingSends(false), + mInKillHardShutdown(false) { MOZ_COUNT_CTOR(ipc::MessageChannel); #ifdef OS_WIN mTopFrame = nullptr; mIsSyncWaitingOnNonMainThread = false; #endif @@ -695,17 +696,20 @@ MessageChannel::Clear() // Also don't clear mListener. If we clear it, then sending a message // through this channel after it's Clear()'ed can cause this process to // crash. // // In practice, mListener owns the channel, so the channel gets deleted // before mListener. But just to be safe, mListener is a weak pointer. #if !defined(ANDROID) - if (!Unsound_IsClosed()) { + // KillHard shutdowns can occur with the channel in connected state. We are + // already collecting crash dump data about KillHard shutdowns and we + // shouldn't intentionally crash here. + if (!Unsound_IsClosed() && !mInKillHardShutdown) { CrashReporter::AnnotateCrashReport( NS_LITERAL_CSTRING("IPCFatalErrorProtocol"), nsDependentCString(mName)); switch (mChannelState) { case ChannelOpening: MOZ_CRASH("MessageChannel destroyed without being closed " \ "(mChannelState == ChannelOpening)."); break; diff --git a/ipc/glue/MessageChannel.h b/ipc/glue/MessageChannel.h --- a/ipc/glue/MessageChannel.h +++ b/ipc/glue/MessageChannel.h @@ -322,16 +322,20 @@ private: static bool IsPumpingMessages() { return sIsPumpingMessages; } static void SetIsPumpingMessages(bool aIsPumping) { sIsPumpingMessages = aIsPumping; } + void SetInKillHardShutdown() { + mInKillHardShutdown = true; + } + #ifdef OS_WIN struct MOZ_STACK_CLASS SyncStackFrame { SyncStackFrame(MessageChannel* channel, bool interrupt); ~SyncStackFrame(); bool mInterrupt; bool mSpinNestedEvents; @@ -849,16 +853,18 @@ private: RefPtr mOnChannelConnectedTask; bool mPeerPidSet; int32_t mPeerPid; // Channels can enter messages are not sent immediately; instead, they are // held in a queue until another thread deems it is safe to send them. bool mIsPostponingSends; std::vector> mPostponedSends; + + bool mInKillHardShutdown; }; void CancelCPOWs(); } // namespace ipc } // namespace mozilla