Bug 1124933 - Include crash reason when intentionally crashing content process (r=bent)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -751,7 +751,7 @@ HangMonitoredProcess::TerminateProcess()
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
mContentParent->KillHard();
|
||||
mContentParent->KillHard("HangMonitor");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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: \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user