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) {
// The DOM in the other process should have kept us from receiving any
// indexedDB messages so assume that the child is misbehaving.
aContentParent->KillHard();
aContentParent->KillHard("IndexedDB CheckPermission 1");
}
return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
}
@@ -10797,14 +10797,14 @@ FactoryOp::CheckPermission(ContentParent* aContentParent,
// Deleting a database requires write permissions.
if (mDeleting && !canWrite) {
aContentParent->KillHard();
aContentParent->KillHard("IndexedDB CheckPermission 2");
IDB_REPORT_INTERNAL_ERR();
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
// Opening or deleting requires read permissions.
if (!canRead) {
aContentParent->KillHard();
aContentParent->KillHard("IndexedDB CheckPermission 3");
IDB_REPORT_INTERNAL_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",
aCapability).get());
static_cast<ContentParent*>(aActor)->KillHard();
static_cast<ContentParent*>(aActor)->KillHard("AssertAppProcess");
return false;
}
@@ -179,7 +179,7 @@ AssertAppStatus(PContentParent* aActor,
"Security problem: Content process does not have `%d' status. It will be killed.",
aStatus).get());
static_cast<ContentParent*>(aActor)->KillHard();
static_cast<ContentParent*>(aActor)->KillHard("AssertAppStatus");
return false;
}
@@ -198,7 +198,7 @@ AssertAppPrincipal(PContentParent* aActor,
{
if (!aPrincipal) {
NS_WARNING("Principal is invalid, killing app process");
static_cast<ContentParent*>(aActor)->KillHard();
static_cast<ContentParent*>(aActor)->KillHard("AssertAppPrincipal");
return false;
}
@@ -220,7 +220,7 @@ AssertAppPrincipal(PContentParent* aActor,
}
NS_WARNING("Principal is invalid, killing app process");
static_cast<ContentParent*>(aActor)->KillHard();
static_cast<ContentParent*>(aActor)->KillHard("AssertAppPrincipal");
return false;
}

View File

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

View File

@@ -441,7 +441,7 @@ public:
private:
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

View File

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

View File

@@ -238,7 +238,7 @@ public:
* in emergency situations since it bypasses the normal shutdown
* process.
*/
void KillHard();
void KillHard(const char* aWhy);
/**
* API for adding a crash reporter annotation that provides a reason
@@ -742,7 +742,7 @@ private:
virtual bool RecvNotifyKeywordSearchLoading(const nsString &aProvider,
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 RecvDeallocateLayerTreeId(const uint64_t& aId) MOZ_OVERRIDE;

View File

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

View File

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

View File

@@ -89,7 +89,7 @@ private:
virtual bool RecvBeginAsyncShutdown() 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);

View File

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

View File

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

View File

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

View File

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

View File

@@ -70,7 +70,7 @@ class MessageListener
virtual Result OnMessageReceived(const Message& aMessage) = 0;
virtual Result OnMessageReceived(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 bool OnReplyTimeout() {
return false;

View File

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

View File

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

View File

@@ -62,7 +62,7 @@ protected:
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
{

View File

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

View File

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

View File

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