зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1504372 - Always generate minidumps for replaying child crashes, r=mccr8.
--HG-- extra : rebase_source : f68f98127fc914339db47f57bf365a950ca2f2b4
This commit is contained in:
Родитель
cb45670d92
Коммит
645f80c048
|
@ -151,6 +151,7 @@ void
|
|||
Channel::SendMessage(const Message& aMsg)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread() ||
|
||||
aMsg.mType == MessageType::BeginFatalError ||
|
||||
aMsg.mType == MessageType::FatalError ||
|
||||
aMsg.mType == MessageType::MiddlemanCallRequest);
|
||||
|
||||
|
|
|
@ -109,8 +109,13 @@ namespace recordreplay {
|
|||
\
|
||||
/* A critical error occurred and execution cannot continue. The child will */ \
|
||||
/* stop executing after sending this message and will wait to be terminated. */ \
|
||||
/* A minidump for the child has been generated. */ \
|
||||
_Macro(FatalError) \
|
||||
\
|
||||
/* Sent when a fatal error has occurred, but before the minidump has been */ \
|
||||
/* generated. */ \
|
||||
_Macro(BeginFatalError) \
|
||||
\
|
||||
/* The child's graphics were repainted. */ \
|
||||
_Macro(Paint) \
|
||||
\
|
||||
|
@ -371,6 +376,8 @@ struct FatalErrorMessage : public Message
|
|||
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.
|
||||
// This needs to match the format expected for canvas image data, to avoid
|
||||
// transforming the data before rendering it in the middleman process.
|
||||
|
|
|
@ -108,8 +108,9 @@ ChannelMessageHandler(Message* aMsg)
|
|||
PrintSpew("Terminate message received, exiting...\n");
|
||||
_exit(0);
|
||||
} else {
|
||||
MOZ_CRASH("Hanged replaying process");
|
||||
ReportFatalError(Nothing(), "Hung replaying process");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MessageType::SetIsActive: {
|
||||
const SetIsActiveMessage& nmsg = (const SetIsActiveMessage&) *aMsg;
|
||||
|
@ -350,6 +351,10 @@ CreateCheckpoint()
|
|||
void
|
||||
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.
|
||||
UnrecoverableSnapshotFailure();
|
||||
|
||||
|
|
|
@ -40,6 +40,8 @@ ChildProcessInfo::ChildProcessInfo(UniquePtr<ChildRole> aRole,
|
|||
, mNumRecoveredMessages(0)
|
||||
, mRole(std::move(aRole))
|
||||
, mPauseNeeded(false)
|
||||
, mHasBegunFatalError(false)
|
||||
, mHasFatalError(false)
|
||||
{
|
||||
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.
|
||||
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);
|
||||
OnCrash(nmsg.Error());
|
||||
return;
|
||||
|
@ -527,12 +533,23 @@ ChildProcessInfo::OnCrash(const char* aWhy)
|
|||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
|
||||
// If a child process crashes or hangs then annotate the crash report and
|
||||
// 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.
|
||||
// If a child process crashes or hangs then annotate the crash report.
|
||||
CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::RecordReplayError,
|
||||
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;
|
||||
} else {
|
||||
// The child is still non-responsive after sending the terminate
|
||||
// message, fail without producing a minidump.
|
||||
// message.
|
||||
OnCrash("Child process non-responsive");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -274,6 +274,11 @@ class ChildProcessInfo
|
|||
// Whether we need this child to pause while the recording is updated.
|
||||
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 OnIncomingRecoveryMessage(const Message& aMsg);
|
||||
void SendNextRecoveryMessage();
|
||||
|
|
Загрузка…
Ссылка в новой задаче