Bug 1124933 - Include crash reason when intentionally crashing content process (r=bent)

This commit is contained in:
Bill McCloskey
2015-02-03 09:09:27 -08:00
parent 7f80d25ce3
commit 021be81884
20 changed files with 60 additions and 54 deletions

View File

@@ -10750,7 +10750,7 @@ FactoryOp::CheckPermission(ContentParent* aContentParent,
if (aContentParent) { if (aContentParent) {
// The DOM in the other process should have kept us from receiving any // The DOM in the other process should have kept us from receiving any
// indexedDB messages so assume that the child is misbehaving. // indexedDB messages so assume that the child is misbehaving.
aContentParent->KillHard(); aContentParent->KillHard("IndexedDB CheckPermission 1");
} }
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR; return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
} }
@@ -10797,14 +10797,14 @@ FactoryOp::CheckPermission(ContentParent* aContentParent,
// Deleting a database requires write permissions. // Deleting a database requires write permissions.
if (mDeleting && !canWrite) { if (mDeleting && !canWrite) {
aContentParent->KillHard(); aContentParent->KillHard("IndexedDB CheckPermission 2");
IDB_REPORT_INTERNAL_ERR(); IDB_REPORT_INTERNAL_ERR();
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
} }
// Opening or deleting requires read permissions. // Opening or deleting requires read permissions.
if (!canRead) { if (!canRead) {
aContentParent->KillHard(); aContentParent->KillHard("IndexedDB CheckPermission 3");
IDB_REPORT_INTERNAL_ERR(); IDB_REPORT_INTERNAL_ERR();
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
} }

View File

@@ -157,7 +157,7 @@ AssertAppProcess(PContentParent* aActor,
"Security problem: Content process does not have `%s'. It will be killed.\n", "Security problem: Content process does not have `%s'. It will be killed.\n",
aCapability).get()); aCapability).get());
static_cast<ContentParent*>(aActor)->KillHard(); static_cast<ContentParent*>(aActor)->KillHard("AssertAppProcess");
return false; return false;
} }
@@ -179,7 +179,7 @@ AssertAppStatus(PContentParent* aActor,
"Security problem: Content process does not have `%d' status. It will be killed.", "Security problem: Content process does not have `%d' status. It will be killed.",
aStatus).get()); aStatus).get());
static_cast<ContentParent*>(aActor)->KillHard(); static_cast<ContentParent*>(aActor)->KillHard("AssertAppStatus");
return false; return false;
} }
@@ -198,7 +198,7 @@ AssertAppPrincipal(PContentParent* aActor,
{ {
if (!aPrincipal) { if (!aPrincipal) {
NS_WARNING("Principal is invalid, killing app process"); NS_WARNING("Principal is invalid, killing app process");
static_cast<ContentParent*>(aActor)->KillHard(); static_cast<ContentParent*>(aActor)->KillHard("AssertAppPrincipal");
return false; return false;
} }
@@ -220,7 +220,7 @@ AssertAppPrincipal(PContentParent* aActor,
} }
NS_WARNING("Principal is invalid, killing app process"); NS_WARNING("Principal is invalid, killing app process");
static_cast<ContentParent*>(aActor)->KillHard(); static_cast<ContentParent*>(aActor)->KillHard("AssertAppPrincipal");
return false; return false;
} }

View File

@@ -1805,9 +1805,9 @@ ContentChild::ActorDestroy(ActorDestroyReason why)
} }
void void
ContentChild::ProcessingError(Result what) ContentChild::ProcessingError(Result aCode, const char* aReason)
{ {
switch (what) { switch (aCode) {
case MsgDropped: case MsgDropped:
NS_WARNING("MsgDropped in ContentChild"); NS_WARNING("MsgDropped in ContentChild");
return; return;

View File

@@ -441,7 +441,7 @@ public:
private: private:
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE; virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
virtual void ProcessingError(Result what) MOZ_OVERRIDE; virtual void ProcessingError(Result aCode, const char* aReason) MOZ_OVERRIDE;
/** /**
* Exit *now*. Do not shut down XPCOM, do not pass Go, do not run * Exit *now*. Do not shut down XPCOM, do not pass Go, do not run

View File

@@ -662,7 +662,7 @@ ContentParent::GetNewOrPreallocatedAppProcess(mozIApplication* aApp,
if (!process->SetPriorityAndCheckIsAlive(aInitialPriority)) { if (!process->SetPriorityAndCheckIsAlive(aInitialPriority)) {
// Kill the process just in case it's not actually dead; we don't want // Kill the process just in case it's not actually dead; we don't want
// to "leak" this process! // to "leak" this process!
process->KillHard(); process->KillHard("GetNewOrPreallocatedAppProcess");
} }
else { else {
nsAutoString manifestURL; nsAutoString manifestURL;
@@ -954,7 +954,7 @@ ContentParent::RecvBridgeToChildProcess(const ContentParentId& aCpId)
} }
// You can't bridge to a process you didn't open! // You can't bridge to a process you didn't open!
KillHard(); KillHard("BridgeToChildProcess");
return false; return false;
} }
@@ -1197,7 +1197,7 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
// other process has already died. // other process has already died.
if (!reused) { if (!reused) {
// Don't leave a broken ContentParent in the hashtable. // Don't leave a broken ContentParent in the hashtable.
parent->AsContentParent()->KillHard(); parent->AsContentParent()->KillHard("CreateBrowserOrApp");
sAppContentParents->Remove(manifestURL); sAppContentParents->Remove(manifestURL);
parent = nullptr; parent = nullptr;
} }
@@ -1581,7 +1581,7 @@ ContentParent::ShutDownProcess(ShutDownMethod aMethod)
// Kill Nuwa process forcibly to break its IPC channels and finalize // Kill Nuwa process forcibly to break its IPC channels and finalize
// corresponding parents. // corresponding parents.
if (IsNuwaProcess()) { if (IsNuwaProcess()) {
KillHard(); KillHard("ShutDownProcess");
} }
#endif #endif
} }
@@ -1739,14 +1739,13 @@ ContentParent::OnChannelConnected(int32_t pid)
} }
void void
ContentParent::ProcessingError(Result what) ContentParent::ProcessingError(Result aCode, const char* aReason)
{ {
if (MsgDropped == what) { if (MsgDropped == aCode) {
// Messages sent after crashes etc. are not a big deal.
return; return;
} }
// Other errors are big deals. // Other errors are big deals.
KillHard(); KillHard(aReason);
} }
typedef std::pair<ContentParent*, std::set<uint64_t> > IDPair; typedef std::pair<ContentParent*, std::set<uint64_t> > IDPair;
@@ -1786,7 +1785,7 @@ ContentParent::RecvDeallocateLayerTreeId(const uint64_t& aId)
CompositorParent::DeallocateLayerTreeId(aId); CompositorParent::DeallocateLayerTreeId(aId);
} else { } else {
// You can't deallocate layer tree ids that you didn't allocate // You can't deallocate layer tree ids that you didn't allocate
KillHard(); KillHard("DeallocateLayerTreeId");
} }
return true; return true;
} }
@@ -2368,7 +2367,7 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority,
} }
#endif #endif
if (shouldSandbox && !SendSetProcessSandbox()) { if (shouldSandbox && !SendSetProcessSandbox()) {
KillHard(); KillHard("SandboxInitFailed");
} }
#endif #endif
} }
@@ -2711,7 +2710,7 @@ ContentParent::RecvNuwaReady()
"Terminating child process %d for unauthorized IPC message: NuwaReady", "Terminating child process %d for unauthorized IPC message: NuwaReady",
Pid()).get()); Pid()).get());
KillHard(); KillHard("NuwaReady");
return false; return false;
} }
sNuwaReady = true; sNuwaReady = true;
@@ -2747,7 +2746,7 @@ ContentParent::RecvAddNewProcess(const uint32_t& aPid,
"Terminating child process %d for unauthorized IPC message: " "Terminating child process %d for unauthorized IPC message: "
"AddNewProcess(%d)", Pid(), aPid).get()); "AddNewProcess(%d)", Pid(), aPid).get());
KillHard(); KillHard("AddNewProcess");
return false; return false;
} }
nsRefPtr<ContentParent> content; nsRefPtr<ContentParent> content;
@@ -3231,11 +3230,11 @@ ContentParent::DeallocPRemoteSpellcheckEngineParent(PRemoteSpellcheckEngineParen
ContentParent::ForceKillTimerCallback(nsITimer* aTimer, void* aClosure) ContentParent::ForceKillTimerCallback(nsITimer* aTimer, void* aClosure)
{ {
auto self = static_cast<ContentParent*>(aClosure); auto self = static_cast<ContentParent*>(aClosure);
self->KillHard(); self->KillHard("ShutDownKill");
} }
void void
ContentParent::KillHard() ContentParent::KillHard(const char* aReason)
{ {
// On Windows, calling KillHard multiple times causes problems - the // On Windows, calling KillHard multiple times causes problems - the
// process handle becomes invalid on the first call, causing a second call // process handle becomes invalid on the first call, causing a second call
@@ -3273,6 +3272,10 @@ ContentParent::KillHard()
NS_LITERAL_CSTRING("kill_hard"), NS_LITERAL_CSTRING("kill_hard"),
GetKillHardAnnotation()); GetKillHardAnnotation());
} }
nsDependentCString reason(aReason);
crashReporter->AnnotateCrashReport(
NS_LITERAL_CSTRING("ipc_channel_error"),
reason);
} }
} }
#endif #endif
@@ -4216,7 +4219,7 @@ ContentParent::CheckAppHasStatus(unsigned short aStatus)
bool bool
ContentParent::KillChild() ContentParent::KillChild()
{ {
KillHard(); KillHard("KillChild");
return true; return true;
} }

View File

@@ -238,7 +238,7 @@ public:
* in emergency situations since it bypasses the normal shutdown * in emergency situations since it bypasses the normal shutdown
* process. * process.
*/ */
void KillHard(); void KillHard(const char* aWhy);
/** /**
* API for adding a crash reporter annotation that provides a reason * API for adding a crash reporter annotation that provides a reason
@@ -742,7 +742,7 @@ private:
virtual bool RecvNotifyKeywordSearchLoading(const nsString &aProvider, virtual bool RecvNotifyKeywordSearchLoading(const nsString &aProvider,
const nsString &aKeyword) MOZ_OVERRIDE; const nsString &aKeyword) MOZ_OVERRIDE;
virtual void ProcessingError(Result what) MOZ_OVERRIDE; virtual void ProcessingError(Result aCode, const char* aMsgName) MOZ_OVERRIDE;
virtual bool RecvAllocateLayerTreeId(uint64_t* aId) MOZ_OVERRIDE; virtual bool RecvAllocateLayerTreeId(uint64_t* aId) MOZ_OVERRIDE;
virtual bool RecvDeallocateLayerTreeId(const uint64_t& aId) MOZ_OVERRIDE; virtual bool RecvDeallocateLayerTreeId(const uint64_t& aId) MOZ_OVERRIDE;

View File

@@ -751,7 +751,7 @@ HangMonitoredProcess::TerminateProcess()
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
} }
mContentParent->KillHard(); mContentParent->KillHard("HangMonitor");
return NS_OK; return NS_OK;
} }

View File

@@ -459,9 +459,9 @@ GMPChild::ActorDestroy(ActorDestroyReason aWhy)
} }
void void
GMPChild::ProcessingError(Result aWhat) GMPChild::ProcessingError(Result aCode, const char* aReason)
{ {
switch (aWhat) { switch (aCode) {
case MsgDropped: case MsgDropped:
_exit(0); // Don't trigger a crash report. _exit(0); // Don't trigger a crash report.
case MsgNotKnown: case MsgNotKnown:

View File

@@ -89,7 +89,7 @@ private:
virtual bool RecvBeginAsyncShutdown() MOZ_OVERRIDE; virtual bool RecvBeginAsyncShutdown() MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
virtual void ProcessingError(Result aWhat) MOZ_OVERRIDE; virtual void ProcessingError(Result aCode, const char* aReason) MOZ_OVERRIDE;
GMPErr GetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI); GMPErr GetAPI(const char* aAPIName, void* aHostAPI, void** aPluginAPI);

View File

@@ -81,13 +81,13 @@ BackgroundChildImpl::~BackgroundChildImpl()
} }
void void
BackgroundChildImpl::ProcessingError(Result aWhat) BackgroundChildImpl::ProcessingError(Result aCode, const char* aReason)
{ {
// May happen on any thread! // May happen on any thread!
nsAutoCString abortMessage; nsAutoCString abortMessage;
switch (aWhat) { switch (aCode) {
#define HANDLE_CASE(_result) \ #define HANDLE_CASE(_result) \
case _result: \ case _result: \

View File

@@ -40,7 +40,7 @@ protected:
virtual ~BackgroundChildImpl(); virtual ~BackgroundChildImpl();
virtual void virtual void
ProcessingError(Result aWhat) MOZ_OVERRIDE; ProcessingError(Result aCode, const char* aReason) MOZ_OVERRIDE;
virtual void virtual void
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE; ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;

View File

@@ -285,20 +285,20 @@ public:
bool isNullPrincipal; bool isNullPrincipal;
nsresult rv = principal->GetIsNullPrincipal(&isNullPrincipal); nsresult rv = principal->GetIsNullPrincipal(&isNullPrincipal);
if (NS_WARN_IF(NS_FAILED(rv)) || isNullPrincipal) { if (NS_WARN_IF(NS_FAILED(rv)) || isNullPrincipal) {
mContentParent->KillHard(); mContentParent->KillHard("PBackground CheckPrincipal 1");
return NS_OK; return NS_OK;
} }
nsCOMPtr<nsIURI> uri; nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), mOrigin); rv = NS_NewURI(getter_AddRefs(uri), mOrigin);
if (NS_FAILED(rv) || !uri) { if (NS_FAILED(rv) || !uri) {
mContentParent->KillHard(); mContentParent->KillHard("PBackground CheckPrincipal 2");
return NS_OK; return NS_OK;
} }
rv = principal->CheckMayLoad(uri, false, false); rv = principal->CheckMayLoad(uri, false, false);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
mContentParent->KillHard(); mContentParent->KillHard("PBackground CheckPrincipal 3");
return NS_OK; return NS_OK;
} }

View File

@@ -1506,7 +1506,7 @@ void
MessageChannel::ReportMessageRouteError(const char* channelName) const MessageChannel::ReportMessageRouteError(const char* channelName) const
{ {
PrintErrorMessage(mSide, channelName, "Need a route"); PrintErrorMessage(mSide, channelName, "Need a route");
mListener->OnProcessingError(MsgRouteError); mListener->OnProcessingError(MsgRouteError, "MsgRouteError");
} }
void void
@@ -1540,7 +1540,7 @@ MessageChannel::ReportConnectionError(const char* aChannelName) const
PrintErrorMessage(mSide, aChannelName, errorMsg); PrintErrorMessage(mSide, aChannelName, errorMsg);
MonitorAutoUnlock unlock(*mMonitor); MonitorAutoUnlock unlock(*mMonitor);
mListener->OnProcessingError(MsgDropped); mListener->OnProcessingError(MsgDropped, errorMsg);
} }
bool bool
@@ -1575,14 +1575,14 @@ MessageChannel::MaybeHandleError(Result code, const Message& aMsg, const char* c
return false; return false;
} }
char printedMsg[512]; char reason[512];
PR_snprintf(printedMsg, sizeof(printedMsg), PR_snprintf(reason, sizeof(reason),
"(msgtype=0x%lX,name=%s) %s", "(msgtype=0x%lX,name=%s) %s",
aMsg.type(), aMsg.name(), errorMsg); aMsg.type(), aMsg.name(), errorMsg);
PrintErrorMessage(mSide, channelName, printedMsg); PrintErrorMessage(mSide, channelName, reason);
mListener->OnProcessingError(code); mListener->OnProcessingError(code, reason);
return false; return false;
} }

View File

@@ -70,7 +70,7 @@ class MessageListener
virtual Result OnMessageReceived(const Message& aMessage) = 0; virtual Result OnMessageReceived(const Message& aMessage) = 0;
virtual Result OnMessageReceived(const Message& aMessage, Message *& aReply) = 0; virtual Result OnMessageReceived(const Message& aMessage, Message *& aReply) = 0;
virtual Result OnCallReceived(const Message& aMessage, Message *& aReply) = 0; virtual Result OnCallReceived(const Message& aMessage, Message *& aReply) = 0;
virtual void OnProcessingError(Result aError) = 0; virtual void OnProcessingError(Result aError, const char* aMsgName) = 0;
virtual void OnChannelConnected(int32_t peer_pid) {} virtual void OnChannelConnected(int32_t peer_pid) {}
virtual bool OnReplyTimeout() { virtual bool OnReplyTimeout() {
return false; return false;

View File

@@ -2886,7 +2886,8 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
# void ProcessingError(code); default to no-op # void ProcessingError(code); default to no-op
processingerror = MethodDefn( processingerror = MethodDefn(
MethodDecl(p.processingErrorVar().name, MethodDecl(p.processingErrorVar().name,
params=[ Param(_Result.Type(), 'aCode') ], params=[ Param(_Result.Type(), 'aCode'),
Param(Type('char', const=1, ptr=1), 'aReason') ],
virtual=1)) virtual=1))
# bool ShouldContinueFromReplyTimeout(); default to |true| # bool ShouldContinueFromReplyTimeout(); default to |true|
@@ -3203,12 +3204,14 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
# OnProcesingError(code) # OnProcesingError(code)
codevar = ExprVar('aCode') codevar = ExprVar('aCode')
reasonvar = ExprVar('aReason')
onprocessingerror = MethodDefn( onprocessingerror = MethodDefn(
MethodDecl('OnProcessingError', MethodDecl('OnProcessingError',
params=[ Param(_Result.Type(), codevar.name) ])) params=[ Param(_Result.Type(), codevar.name),
Param(Type('char', const=1, ptr=1), reasonvar.name) ]))
if ptype.isToplevel(): if ptype.isToplevel():
onprocessingerror.addstmt(StmtReturn( onprocessingerror.addstmt(StmtReturn(
ExprCall(p.processingErrorVar(), args=[ codevar ]))) ExprCall(p.processingErrorVar(), args=[ codevar, reasonvar ])))
else: else:
onprocessingerror.addstmt( onprocessingerror.addstmt(
_runtimeAbort("`OnProcessingError' called on non-toplevel actor")) _runtimeAbort("`OnProcessingError' called on non-toplevel actor"))

View File

@@ -108,7 +108,7 @@ TestFailedCtorChild::DeallocPTestFailedCtorSubChild(PTestFailedCtorSubChild* act
} }
void void
TestFailedCtorChild::ProcessingError(Result what) TestFailedCtorChild::ProcessingError(Result aCode, const char* aReason)
{ {
if (OtherProcess() != 0) // thread-mode if (OtherProcess() != 0) // thread-mode
_exit(0); _exit(0);

View File

@@ -62,7 +62,7 @@ protected:
virtual bool DeallocPTestFailedCtorSubChild(PTestFailedCtorSubChild* actor) MOZ_OVERRIDE; virtual bool DeallocPTestFailedCtorSubChild(PTestFailedCtorSubChild* actor) MOZ_OVERRIDE;
virtual void ProcessingError(Result what) MOZ_OVERRIDE; virtual void ProcessingError(Result aCode, const char* aReason) MOZ_OVERRIDE;
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
{ {

View File

@@ -122,9 +122,9 @@ TestInterruptErrorCleanupParent::Main()
} }
void void
TestInterruptErrorCleanupParent::ProcessingError(Result what) TestInterruptErrorCleanupParent::ProcessingError(Result aCode, const char* aReason)
{ {
if (what != MsgDropped) if (aCode != MsgDropped)
fail("unexpected processing error"); fail("unexpected processing error");
mGotProcessingError = true; mGotProcessingError = true;
} }

View File

@@ -30,7 +30,7 @@ protected:
fail("unexpected destruction!"); fail("unexpected destruction!");
} }
virtual void ProcessingError(Result what) MOZ_OVERRIDE; virtual void ProcessingError(Result aCode, const char* aReason) MOZ_OVERRIDE;
bool mGotProcessingError; bool mGotProcessingError;
}; };

View File

@@ -25,7 +25,7 @@ public:
protected: protected:
virtual bool RecvError() MOZ_OVERRIDE; virtual bool RecvError() MOZ_OVERRIDE;
virtual void ProcessingError(Result what) MOZ_OVERRIDE virtual void ProcessingError(Result aCode, const char* aReason) MOZ_OVERRIDE
{ {
// Ignore errors // Ignore errors
} }
@@ -50,7 +50,7 @@ public:
protected: protected:
virtual bool RecvStart() MOZ_OVERRIDE; virtual bool RecvStart() MOZ_OVERRIDE;
virtual void ProcessingError(Result what) MOZ_OVERRIDE virtual void ProcessingError(Result aCode, const char* aReason) MOZ_OVERRIDE
{ {
// Ignore errors // Ignore errors
} }