mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-23 02:05:42 +00:00
Bug 1504372 - Always generate minidumps for replaying child crashes, r=mccr8.
--HG-- extra : rebase_source : f68f98127fc914339db47f57bf365a950ca2f2b4
This commit is contained in:
parent
cb45670d92
commit
645f80c048
@ -151,6 +151,7 @@ void
|
|||||||
Channel::SendMessage(const Message& aMsg)
|
Channel::SendMessage(const Message& aMsg)
|
||||||
{
|
{
|
||||||
MOZ_RELEASE_ASSERT(NS_IsMainThread() ||
|
MOZ_RELEASE_ASSERT(NS_IsMainThread() ||
|
||||||
|
aMsg.mType == MessageType::BeginFatalError ||
|
||||||
aMsg.mType == MessageType::FatalError ||
|
aMsg.mType == MessageType::FatalError ||
|
||||||
aMsg.mType == MessageType::MiddlemanCallRequest);
|
aMsg.mType == MessageType::MiddlemanCallRequest);
|
||||||
|
|
||||||
|
@ -109,8 +109,13 @@ namespace recordreplay {
|
|||||||
\
|
\
|
||||||
/* A critical error occurred and execution cannot continue. The child will */ \
|
/* A critical error occurred and execution cannot continue. The child will */ \
|
||||||
/* stop executing after sending this message and will wait to be terminated. */ \
|
/* stop executing after sending this message and will wait to be terminated. */ \
|
||||||
|
/* A minidump for the child has been generated. */ \
|
||||||
_Macro(FatalError) \
|
_Macro(FatalError) \
|
||||||
\
|
\
|
||||||
|
/* Sent when a fatal error has occurred, but before the minidump has been */ \
|
||||||
|
/* generated. */ \
|
||||||
|
_Macro(BeginFatalError) \
|
||||||
|
\
|
||||||
/* The child's graphics were repainted. */ \
|
/* The child's graphics were repainted. */ \
|
||||||
_Macro(Paint) \
|
_Macro(Paint) \
|
||||||
\
|
\
|
||||||
@ -371,6 +376,8 @@ struct FatalErrorMessage : public Message
|
|||||||
const char* Error() const { return Data<FatalErrorMessage, const char>(); }
|
const char* Error() const { return Data<FatalErrorMessage, const char>(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef EmptyMessage<MessageType::BeginFatalError> BeginFatalErrorMessage;
|
||||||
|
|
||||||
// The format for graphics data which will be sent to the middleman process.
|
// The format for graphics data which will be sent to the middleman process.
|
||||||
// This needs to match the format expected for canvas image data, to avoid
|
// This needs to match the format expected for canvas image data, to avoid
|
||||||
// transforming the data before rendering it in the middleman process.
|
// transforming the data before rendering it in the middleman process.
|
||||||
|
@ -108,8 +108,9 @@ ChannelMessageHandler(Message* aMsg)
|
|||||||
PrintSpew("Terminate message received, exiting...\n");
|
PrintSpew("Terminate message received, exiting...\n");
|
||||||
_exit(0);
|
_exit(0);
|
||||||
} else {
|
} else {
|
||||||
MOZ_CRASH("Hanged replaying process");
|
ReportFatalError(Nothing(), "Hung replaying process");
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case MessageType::SetIsActive: {
|
case MessageType::SetIsActive: {
|
||||||
const SetIsActiveMessage& nmsg = (const SetIsActiveMessage&) *aMsg;
|
const SetIsActiveMessage& nmsg = (const SetIsActiveMessage&) *aMsg;
|
||||||
@ -350,6 +351,10 @@ CreateCheckpoint()
|
|||||||
void
|
void
|
||||||
ReportFatalError(const Maybe<MinidumpInfo>& aMinidump, const char* aFormat, ...)
|
ReportFatalError(const Maybe<MinidumpInfo>& aMinidump, const char* aFormat, ...)
|
||||||
{
|
{
|
||||||
|
// Notify the middleman that we are crashing and are going to try to write a
|
||||||
|
// minidump.
|
||||||
|
gChannel->SendMessage(BeginFatalErrorMessage());
|
||||||
|
|
||||||
// Unprotect any memory which might be written while producing the minidump.
|
// Unprotect any memory which might be written while producing the minidump.
|
||||||
UnrecoverableSnapshotFailure();
|
UnrecoverableSnapshotFailure();
|
||||||
|
|
||||||
|
@ -40,6 +40,8 @@ ChildProcessInfo::ChildProcessInfo(UniquePtr<ChildRole> aRole,
|
|||||||
, mNumRecoveredMessages(0)
|
, mNumRecoveredMessages(0)
|
||||||
, mRole(std::move(aRole))
|
, mRole(std::move(aRole))
|
||||||
, mPauseNeeded(false)
|
, mPauseNeeded(false)
|
||||||
|
, mHasBegunFatalError(false)
|
||||||
|
, mHasFatalError(false)
|
||||||
{
|
{
|
||||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
@ -199,7 +201,11 @@ ChildProcessInfo::OnIncomingMessage(size_t aChannelId, const Message& aMsg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Always handle fatal errors in the same way.
|
// Always handle fatal errors in the same way.
|
||||||
if (aMsg.mType == MessageType::FatalError) {
|
if (aMsg.mType == MessageType::BeginFatalError) {
|
||||||
|
mHasBegunFatalError = true;
|
||||||
|
return;
|
||||||
|
} else if (aMsg.mType == MessageType::FatalError) {
|
||||||
|
mHasFatalError = true;
|
||||||
const FatalErrorMessage& nmsg = static_cast<const FatalErrorMessage&>(aMsg);
|
const FatalErrorMessage& nmsg = static_cast<const FatalErrorMessage&>(aMsg);
|
||||||
OnCrash(nmsg.Error());
|
OnCrash(nmsg.Error());
|
||||||
return;
|
return;
|
||||||
@ -527,12 +533,23 @@ ChildProcessInfo::OnCrash(const char* aWhy)
|
|||||||
{
|
{
|
||||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
// If a child process crashes or hangs then annotate the crash report and
|
// If a child process crashes or hangs then annotate the crash report.
|
||||||
// shut down cleanly so that we don't mask the report with our own crash.
|
|
||||||
// We want the crash to happen quickly so the user doesn't get a hanged tab.
|
|
||||||
CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::RecordReplayError,
|
CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::RecordReplayError,
|
||||||
nsAutoCString(aWhy));
|
nsAutoCString(aWhy));
|
||||||
Shutdown();
|
|
||||||
|
// If we received a FatalError message then the child generated a minidump.
|
||||||
|
// Shut down cleanly so that we don't mask the report with our own crash.
|
||||||
|
if (mHasFatalError) {
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicate when we crash if the child tried to send us a fatal error message
|
||||||
|
// but had a problem either unprotecting system memory or generating the
|
||||||
|
// minidump.
|
||||||
|
MOZ_RELEASE_ASSERT(!mHasBegunFatalError);
|
||||||
|
|
||||||
|
// The child crashed without producing a minidump, produce one ourselves.
|
||||||
|
MOZ_CRASH("Unexpected child crash");
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -613,7 +630,7 @@ ChildProcessInfo::WaitUntil(const std::function<bool()>& aCallback)
|
|||||||
sentTerminateMessage = true;
|
sentTerminateMessage = true;
|
||||||
} else {
|
} else {
|
||||||
// The child is still non-responsive after sending the terminate
|
// The child is still non-responsive after sending the terminate
|
||||||
// message, fail without producing a minidump.
|
// message.
|
||||||
OnCrash("Child process non-responsive");
|
OnCrash("Child process non-responsive");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -274,6 +274,11 @@ class ChildProcessInfo
|
|||||||
// Whether we need this child to pause while the recording is updated.
|
// Whether we need this child to pause while the recording is updated.
|
||||||
bool mPauseNeeded;
|
bool mPauseNeeded;
|
||||||
|
|
||||||
|
// Flags for whether we have received messages from the child indicating it
|
||||||
|
// is crashing.
|
||||||
|
bool mHasBegunFatalError;
|
||||||
|
bool mHasFatalError;
|
||||||
|
|
||||||
void OnIncomingMessage(size_t aChannelId, const Message& aMsg);
|
void OnIncomingMessage(size_t aChannelId, const Message& aMsg);
|
||||||
void OnIncomingRecoveryMessage(const Message& aMsg);
|
void OnIncomingRecoveryMessage(const Message& aMsg);
|
||||||
void SendNextRecoveryMessage();
|
void SendNextRecoveryMessage();
|
||||||
|
Loading…
Reference in New Issue
Block a user