Switch PPluginModule from PCrashReporter to shmem-based CrashReportHost/Client. (bug 1338281 part 5, r=billm)

This commit is contained in:
David Anderson 2017-02-15 14:44:30 -08:00
Родитель 0c95d36053
Коммит 3a24634204
10 изменённых файлов: 199 добавлений и 321 удалений

Просмотреть файл

@ -24,11 +24,6 @@ CrashReporterChild::GetCrashReporter()
reporters = &child->ManagedPCrashReporterChild();
break;
}
case GeckoProcessType_Plugin: {
PluginModuleChild* child = PluginModuleChild::GetChrome();
reporters = &child->ManagedPCrashReporterChild();
break;
}
default:
break;
}

Просмотреть файл

@ -40,34 +40,6 @@ public:
bool
GenerateCrashReport(Toplevel* t, const AnnotationTable* processNotes);
/*
* Attempt to generate a parent/child pair of minidumps from the given
* toplevel actor. This calls CrashReporter::CreateMinidumpsAndPair to
* generate the minidumps. Crash reporter annotations set prior to this
* call will be saved via PairedDumpCallbackExtra into an .extra file
* under the proper crash id. AnnotateCrashReport annotations are not
* set in this call and the report is not finalized.
*
* @returns true if successful, false otherwise.
*/
template<class Toplevel>
bool
GeneratePairedMinidump(Toplevel* t);
/*
* Attempts to take a minidump of the current process and pair that with
* a named minidump handed in by the caller.
*
* @param aTopLevel - top level actor this reporter is associated with.
* @param aMinidump - the minidump to associate with.
* @param aPairName - the name of the additional minidump.
* @returns true if successful, false otherwise.
*/
template<class Toplevel>
bool
GenerateMinidumpAndPair(Toplevel* aTopLevel, nsIFile* aMinidump,
const nsACString& aPairName);
/**
* Apply child process annotations to an existing paired mindump generated
* with GeneratePairedMinidump.
@ -115,15 +87,6 @@ public:
bool
GenerateCrashReportForMinidump(nsIFile* minidump,
const AnnotationTable* processNotes);
/*
* Instantiate a new crash reporter actor from a given parent that manages
* the protocol.
*
* @returns true if successful, false otherwise.
*/
template<class Toplevel>
static bool CreateCrashReporter(Toplevel* actor);
#endif // MOZ_CRASHREPORTER
/*
@ -179,59 +142,6 @@ public:
};
#ifdef MOZ_CRASHREPORTER
template<class Toplevel>
inline bool
CrashReporterParent::GeneratePairedMinidump(Toplevel* t)
{
mozilla::ipc::ScopedProcessHandle child;
#ifdef XP_MACOSX
child = t->Process()->GetChildTask();
#else
if (!base::OpenPrivilegedProcessHandle(t->OtherPid(), &child.rwget())) {
NS_WARNING("Failed to open child process handle.");
return false;
}
#endif
nsCOMPtr<nsIFile> childDump;
if (CrashReporter::CreateMinidumpsAndPair(child,
mMainThread,
NS_LITERAL_CSTRING("browser"),
nullptr, // pair with a dump of this process and thread
getter_AddRefs(childDump)) &&
CrashReporter::GetIDFromMinidump(childDump, mChildDumpID)) {
return true;
}
return false;
}
template<class Toplevel>
inline bool
CrashReporterParent::GenerateMinidumpAndPair(Toplevel* aTopLevel,
nsIFile* aMinidumpToPair,
const nsACString& aPairName)
{
mozilla::ipc::ScopedProcessHandle childHandle;
#ifdef XP_MACOSX
childHandle = aTopLevel->Process()->GetChildTask();
#else
if (!base::OpenPrivilegedProcessHandle(aTopLevel->OtherPid(),
&childHandle.rwget())) {
NS_WARNING("Failed to open child process handle.");
return false;
}
#endif
nsCOMPtr<nsIFile> targetDump;
if (CrashReporter::CreateMinidumpsAndPair(childHandle,
mMainThread, // child thread id
aPairName,
aMinidumpToPair,
getter_AddRefs(targetDump)) &&
CrashReporter::GetIDFromMinidump(targetDump, mChildDumpID)) {
return true;
}
return false;
}
template<class Toplevel>
inline bool
CrashReporterParent::GenerateCrashReport(Toplevel* t,
@ -279,25 +189,6 @@ CrashReporterParent::GenerateCompleteMinidump(Toplevel* t)
return false;
}
template<class Toplevel>
/* static */ bool
CrashReporterParent::CreateCrashReporter(Toplevel* actor)
{
#ifdef MOZ_CRASHREPORTER
NativeThreadId id;
uint32_t processType;
PCrashReporterParent* p =
actor->CallPCrashReporterConstructor(&id, &processType);
if (p) {
static_cast<CrashReporterParent*>(p)->SetChildData(id, processType);
} else {
NS_ERROR("Error creating crash reporter actor");
}
return !!p;
#endif
return false;
}
#endif
} // namespace dom

Просмотреть файл

@ -20,7 +20,7 @@ struct Mapping {
};
async protocol PCrashReporter {
manager PContent or PPluginModule;
manager PContent;
parent:
async AnnotateCrashReport(nsCString key, nsCString data);
async AppendAppNotes(nsCString data);

Просмотреть файл

@ -5,7 +5,6 @@
include protocol PPluginInstance;
include protocol PPluginScriptableObject;
include protocol PCrashReporter;
include protocol PContent;
include ProfilerTypes;
@ -37,7 +36,6 @@ struct PluginSettings
intr protocol PPluginModule
{
manages PPluginInstance;
manages PCrashReporter;
both:
// Window-specific message which instructs the interrupt mechanism to enter
@ -92,8 +90,8 @@ child:
async SetParentHangTimeout(uint32_t seconds);
intr PCrashReporter()
returns (NativeThreadId tid, uint32_t processType);
intr InitCrashReporter(Shmem shmem)
returns (NativeThreadId tid);
/**
* Control the Gecko Profiler in the plugin process.

Просмотреть файл

@ -50,14 +50,16 @@
#include "PluginUtilsOSX.h"
#endif
#ifdef MOZ_CRASHREPORTER
#include "mozilla/ipc/CrashReporterClient.h"
#endif
#include "GeckoProfiler.h"
using namespace mozilla;
using namespace mozilla::ipc;
using namespace mozilla::plugins;
using namespace mozilla::widget;
using mozilla::dom::CrashReporterChild;
using mozilla::dom::PCrashReporterChild;
#if defined(XP_WIN)
const wchar_t * kFlashFullscreenClass = L"ShockwaveFlashFullScreen";
@ -720,29 +722,13 @@ PluginModuleChild::RecvInitPluginModuleChild(Endpoint<PPluginModuleChild>&& aEnd
return IPC_OK();
}
PCrashReporterChild*
PluginModuleChild::AllocPCrashReporterChild(mozilla::dom::NativeThreadId* id,
uint32_t* processType)
{
return new CrashReporterChild();
}
bool
PluginModuleChild::DeallocPCrashReporterChild(PCrashReporterChild* actor)
{
delete actor;
return true;
}
mozilla::ipc::IPCResult
PluginModuleChild::AnswerPCrashReporterConstructor(
PCrashReporterChild* actor,
mozilla::dom::NativeThreadId* id,
uint32_t* processType)
PluginModuleChild::AnswerInitCrashReporter(Shmem&& aShmem, mozilla::dom::NativeThreadId* aOutId)
{
#ifdef MOZ_CRASHREPORTER
*id = CrashReporter::CurrentThreadId();
*processType = XRE_GetProcessType();
CrashReporterClient::InitSingletonWithShmem(aShmem);
*aOutId = CrashReporter::CurrentThreadId();
#endif
return IPC_OK();
}
@ -775,6 +761,9 @@ PluginModuleChild::ActorDestroy(ActorDestroyReason why)
// doesn't matter why we're being destroyed; it's up to us to
// initiate (clean) shutdown
#ifdef MOZ_CRASHREPORTER
CrashReporterClient::DestroySingleton();
#endif
XRE_ShutdownChildProcess();
}

Просмотреть файл

@ -46,17 +46,12 @@ typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINUNIXINIT) (const NPNetscapeFun
typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINSHUTDOWN) (void);
namespace mozilla {
namespace dom {
class PCrashReporterChild;
} // namespace dom
namespace plugins {
class PluginInstanceChild;
class PluginModuleChild : public PPluginModuleChild
{
typedef mozilla::dom::PCrashReporterChild PCrashReporterChild;
protected:
virtual mozilla::ipc::RacyInterruptPolicy
MediateInterruptRace(const MessageInfo& parent,
@ -123,15 +118,8 @@ protected:
virtual mozilla::ipc::IPCResult
RecvSetParentHangTimeout(const uint32_t& aSeconds) override;
virtual PCrashReporterChild*
AllocPCrashReporterChild(mozilla::dom::NativeThreadId* id,
uint32_t* processType) override;
virtual bool
DeallocPCrashReporterChild(PCrashReporterChild* actor) override;
virtual mozilla::ipc::IPCResult
AnswerPCrashReporterConstructor(PCrashReporterChild* actor,
mozilla::dom::NativeThreadId* id,
uint32_t* processType) override;
AnswerInitCrashReporter(Shmem&& aShmem, mozilla::dom::NativeThreadId* aId) override;
virtual void
ActorDestroy(ActorDestroyReason why) override;

Просмотреть файл

@ -10,7 +10,6 @@
#include "mozilla/Attributes.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/PCrashReporterParent.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/ipc/MessageChannel.h"
#include "mozilla/ipc/ProtocolUtils.h"
@ -67,15 +66,14 @@ using mozilla::ProfileGatherer;
#endif
using mozilla::ipc::MessageChannel;
using mozilla::ipc::GeckoChildProcessHost;
using mozilla::dom::PCrashReporterParent;
using mozilla::dom::CrashReporterParent;
using namespace mozilla;
using namespace mozilla::plugins;
using namespace mozilla::plugins::parent;
#ifdef MOZ_CRASHREPORTER
#include "mozilla/dom/CrashReporterParent.h"
#include "mozilla/ipc/CrashReporterClient.h"
#include "mozilla/ipc/CrashReporterHost.h"
using namespace CrashReporter;
#endif
@ -598,25 +596,12 @@ PluginModuleChromeParent::OnProcessLaunched(const bool aSucceeded)
#ifdef MOZ_CRASHREPORTER
// If this fails, we're having IPC troubles, and we're doomed anyways.
if (!CrashReporterParent::CreateCrashReporter(this)) {
if (!InitCrashReporter()) {
mShutdown = true;
Close();
OnInitFailure();
return;
}
CrashReporterParent* crashReporter = CrashReporter();
if (crashReporter) {
crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("AsyncPluginInit"),
mIsStartingAsync ?
NS_LITERAL_CSTRING("1") :
NS_LITERAL_CSTRING("0"));
}
#ifdef XP_WIN
{ // Scope for lock
mozilla::MutexAutoLock lock(mCrashReporterMutex);
mCrashReporter = CrashReporter();
}
#endif
#endif
#if defined(XP_WIN) && defined(_X86_)
@ -686,6 +671,37 @@ PluginModuleChromeParent::WaitForIPCConnection()
return true;
}
bool
PluginModuleChromeParent::InitCrashReporter()
{
#ifdef MOZ_CRASHREPORTER
ipc::Shmem shmem;
if (!ipc::CrashReporterClient::AllocShmem(this, &shmem)) {
return false;
}
NativeThreadId threadId;
if (!CallInitCrashReporter(shmem, &threadId)) {
return false;
}
{
mozilla::MutexAutoLock lock(mCrashReporterMutex);
mCrashReporter = MakeUnique<ipc::CrashReporterHost>(
GeckoProcessType_Plugin,
shmem,
threadId);
mCrashReporter->AddNote(NS_LITERAL_CSTRING("AsyncPluginInit"),
mIsStartingAsync ?
NS_LITERAL_CSTRING("1") :
NS_LITERAL_CSTRING("0"));
}
#endif
return true;
}
PluginModuleParent::PluginModuleParent(bool aIsChrome, bool aAllowAsyncInit)
: mQuirks(QUIRKS_NOT_INITIALIZED)
, mIsChrome(aIsChrome)
@ -703,6 +719,9 @@ PluginModuleParent::PluginModuleParent(bool aIsChrome, bool aAllowAsyncInit)
, mNPInitialized(false)
, mIsNPShutdownPending(false)
, mAsyncNewRv(NS_ERROR_NOT_INITIALIZED)
#ifdef MOZ_CRASHREPORTER
, mCrashReporterMutex("PluginModuleChromeParent::mCrashReporterMutex")
#endif
{
#if defined(MOZ_CRASHREPORTER)
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AsyncPluginInit"),
@ -752,10 +771,6 @@ PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath,
, mHangUIParent(nullptr)
, mHangUIEnabled(true)
, mIsTimerReset(true)
#ifdef MOZ_CRASHREPORTER
, mCrashReporterMutex("PluginModuleChromeParent::mCrashReporterMutex")
, mCrashReporter(nullptr)
#endif
#endif
#ifdef MOZ_CRASHREPORTER_INJECTOR
, mFlashProcess1(0)
@ -838,12 +853,11 @@ PluginModuleChromeParent::~PluginModuleChromeParent()
#ifdef MOZ_CRASHREPORTER
void
PluginModuleChromeParent::WriteExtraDataForMinidump(AnnotationTable& notes)
PluginModuleChromeParent::WriteExtraDataForMinidump()
{
#ifdef XP_WIN
// mCrashReporterMutex is already held by the caller
mCrashReporterMutex.AssertCurrentThreadOwns();
#endif
typedef nsDependentCString CS;
// Get the plugin filename, try to get just the file leafname
@ -853,27 +867,26 @@ PluginModuleChromeParent::WriteExtraDataForMinidump(AnnotationTable& notes)
filePos = 0;
else
filePos++;
notes.Put(NS_LITERAL_CSTRING("PluginFilename"), CS(pluginFile.substr(filePos).c_str()));
mCrashReporter->AddNote(NS_LITERAL_CSTRING("PluginFilename"), CS(pluginFile.substr(filePos).c_str()));
notes.Put(NS_LITERAL_CSTRING("PluginName"), mPluginName);
notes.Put(NS_LITERAL_CSTRING("PluginVersion"), mPluginVersion);
mCrashReporter->AddNote(NS_LITERAL_CSTRING("PluginName"), mPluginName);
mCrashReporter->AddNote(NS_LITERAL_CSTRING("PluginVersion"), mPluginVersion);
CrashReporterParent* crashReporter = CrashReporter();
if (crashReporter) {
if (mCrashReporter) {
#ifdef XP_WIN
if (mPluginCpuUsageOnHang.Length() > 0) {
notes.Put(NS_LITERAL_CSTRING("NumberOfProcessors"),
nsPrintfCString("%d", PR_GetNumberOfProcessors()));
mCrashReporter->AddNote(NS_LITERAL_CSTRING("NumberOfProcessors"),
nsPrintfCString("%d", PR_GetNumberOfProcessors()));
nsCString cpuUsageStr;
cpuUsageStr.AppendFloat(std::ceil(mPluginCpuUsageOnHang[0] * 100) / 100);
notes.Put(NS_LITERAL_CSTRING("PluginCpuUsage"), cpuUsageStr);
mCrashReporter->AddNote(NS_LITERAL_CSTRING("PluginCpuUsage"), cpuUsageStr);
#ifdef MOZ_CRASHREPORTER_INJECTOR
for (uint32_t i=1; i<mPluginCpuUsageOnHang.Length(); ++i) {
nsCString tempStr;
tempStr.AppendFloat(std::ceil(mPluginCpuUsageOnHang[i] * 100) / 100);
notes.Put(nsPrintfCString("CpuUsageFlashProcess%d", i), tempStr);
mCrashReporter->AddNote(nsPrintfCString("CpuUsageFlashProcess%d", i), tempStr);
}
#endif
}
@ -1203,12 +1216,9 @@ PluginModuleChromeParent::TakeFullMinidump(base::ProcessId aContentPid,
nsString& aDumpId)
{
#ifdef MOZ_CRASHREPORTER
#ifdef XP_WIN
mozilla::MutexAutoLock lock(mCrashReporterMutex);
#endif // XP_WIN
CrashReporterParent* crashReporter = CrashReporter();
if (!crashReporter) {
if (!mCrashReporter) {
return;
}
@ -1227,8 +1237,11 @@ PluginModuleChromeParent::TakeFullMinidump(base::ProcessId aContentPid,
{
// We have a single browser report, generate a new plugin process parent
// report and pair it up with the browser report handed in.
reportsReady = crashReporter->GenerateMinidumpAndPair(this, browserDumpFile,
NS_LITERAL_CSTRING("browser"));
reportsReady = mCrashReporter->GenerateMinidumpAndPair(
this,
browserDumpFile,
NS_LITERAL_CSTRING("browser"));
if (!reportsReady) {
browserDumpFile = nullptr;
CrashReporter::DeleteMinidumpFilesForID(aBrowserDumpId);
@ -1240,20 +1253,20 @@ PluginModuleChromeParent::TakeFullMinidump(base::ProcessId aContentPid,
// the browser process, content process when running under e10s, and
// various flash subprocesses if we're the flash module.
if (!reportsReady) {
reportsReady = crashReporter->GeneratePairedMinidump(this);
reportsReady = mCrashReporter->GenerateMinidumpAndPair(
this,
nullptr, // Pair with a dump of this process and thread.
NS_LITERAL_CSTRING("browser"));
}
if (reportsReady) {
// Important to set this here, it tells the ActorDestroy handler
// that we have an existing crash report that needs to be finalized.
mPluginDumpID = crashReporter->ChildDumpID();
aDumpId = mPluginDumpID;
aDumpId = mCrashReporter->MinidumpID();
PLUGIN_LOG_DEBUG(
("generated paired browser/plugin minidumps: %s)",
NS_ConvertUTF16toUTF8(mPluginDumpID).get()));
NS_ConvertUTF16toUTF8(aDumpId).get()));
nsAutoCString additionalDumps("browser");
nsCOMPtr<nsIFile> pluginDumpFile;
if (GetMinidumpForID(mPluginDumpID, getter_AddRefs(pluginDumpFile)) &&
if (GetMinidumpForID(aDumpId, getter_AddRefs(pluginDumpFile)) &&
pluginDumpFile) {
#ifdef MOZ_CRASHREPORTER_INJECTOR
// If we have handles to the flash sandbox processes on Windows,
@ -1276,7 +1289,7 @@ PluginModuleChromeParent::TakeFullMinidump(base::ProcessId aContentPid,
}
}
}
crashReporter->AnnotateCrashReport(
mCrashReporter->AddNote(
NS_LITERAL_CSTRING("additional_minidumps"),
additionalDumps);
} else {
@ -1294,33 +1307,28 @@ PluginModuleChromeParent::TerminateChildProcess(MessageLoop* aMsgLoop,
#ifdef MOZ_CRASHREPORTER
// Start by taking a full minidump if necessary, this is done early
// because it also needs to lock the mCrashReporterMutex and Mutex doesn't
// support recrusive locking.
// support recursive locking.
nsAutoString dumpId;
if (aDumpId.IsEmpty()) {
TakeFullMinidump(aContentPid, EmptyString(), dumpId);
}
#ifdef XP_WIN
mozilla::MutexAutoLock lock(mCrashReporterMutex);
CrashReporterParent* crashReporter = mCrashReporter;
if (!crashReporter) {
if (!mCrashReporter) {
// If mCrashReporter is null then the hang has ended, the plugin module
// is shutting down. There's nothing to do here.
return;
}
#else
CrashReporterParent* crashReporter = CrashReporter();
#endif // XP_WIN
crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("PluginHang"),
NS_LITERAL_CSTRING("1"));
crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("HangMonitorDescription"),
aMonitorDescription);
mCrashReporter->AddNote(NS_LITERAL_CSTRING("PluginHang"),
NS_LITERAL_CSTRING("1"));
mCrashReporter->AddNote(NS_LITERAL_CSTRING("HangMonitorDescription"),
aMonitorDescription);
#ifdef XP_WIN
if (mHangUIParent) {
unsigned int hangUIDuration = mHangUIParent->LastShowDurationMs();
if (hangUIDuration) {
nsPrintfCString strHangUIDuration("%u", hangUIDuration);
crashReporter->AnnotateCrashReport(
mCrashReporter->AddNote(
NS_LITERAL_CSTRING("PluginHangUIDuration"),
strHangUIDuration);
}
@ -1501,12 +1509,6 @@ PluginModuleChromeParent::OnHangUIContinue()
#endif // XP_WIN
#ifdef MOZ_CRASHREPORTER
CrashReporterParent*
PluginModuleChromeParent::CrashReporter()
{
return static_cast<CrashReporterParent*>(LoneManagedOrNullAsserts(ManagedPCrashReporterParent()));
}
#ifdef MOZ_CRASHREPORTER_INJECTOR
static void
RemoveMinidump(nsIFile* minidump)
@ -1526,31 +1528,26 @@ RemoveMinidump(nsIFile* minidump)
void
PluginModuleChromeParent::ProcessFirstMinidump()
{
#ifdef XP_WIN
mozilla::MutexAutoLock lock(mCrashReporterMutex);
#endif
CrashReporterParent* crashReporter = CrashReporter();
if (!crashReporter)
if (!mCrashReporter)
return;
AnnotationTable notes(4);
WriteExtraDataForMinidump(notes);
WriteExtraDataForMinidump();
if (!mPluginDumpID.IsEmpty()) {
// mPluginDumpID may be set in TerminateChildProcess, which means the
if (mCrashReporter->HasMinidump()) {
// A minidump may be set in TerminateChildProcess, which means the
// process hang monitor has already collected a 3-way browser, plugin,
// content crash report. If so, update the existing report with our
// annotations and finalize it. If not, fall through for standard
// plugin crash report handling.
crashReporter->GenerateChildData(&notes);
crashReporter->FinalizeChildData();
mCrashReporter->FinalizeCrashReport();
return;
}
uint32_t sequence = UINT32_MAX;
nsCOMPtr<nsIFile> dumpFile;
nsAutoCString flashProcessType;
TakeMinidump(getter_AddRefs(dumpFile), &sequence);
RefPtr<nsIFile> dumpFile = mCrashReporter->TakeCrashedChildMinidump(OtherPid(), &sequence);
#ifdef MOZ_CRASHREPORTER_INJECTOR
nsCOMPtr<nsIFile> childDumpFile;
@ -1560,7 +1557,9 @@ PluginModuleChromeParent::ProcessFirstMinidump()
TakeMinidumpForChild(mFlashProcess1,
getter_AddRefs(childDumpFile),
&childSequence)) {
if (childSequence < sequence) {
if (childSequence < sequence &&
mCrashReporter->AdoptMinidump(childDumpFile))
{
RemoveMinidump(dumpFile);
dumpFile = childDumpFile;
sequence = childSequence;
@ -1574,7 +1573,9 @@ PluginModuleChromeParent::ProcessFirstMinidump()
TakeMinidumpForChild(mFlashProcess2,
getter_AddRefs(childDumpFile),
&childSequence)) {
if (childSequence < sequence) {
if (childSequence < sequence &&
mCrashReporter->AdoptMinidump(childDumpFile))
{
RemoveMinidump(dumpFile);
dumpFile = childDumpFile;
sequence = childSequence;
@ -1592,13 +1593,12 @@ PluginModuleChromeParent::ProcessFirstMinidump()
}
PLUGIN_LOG_DEBUG(("got child minidump: %s",
NS_ConvertUTF16toUTF8(mPluginDumpID).get()));
NS_ConvertUTF16toUTF8(mCrashReporter->MinidumpID()).get()));
GetIDFromMinidump(dumpFile, mPluginDumpID);
if (!flashProcessType.IsEmpty()) {
notes.Put(NS_LITERAL_CSTRING("FlashProcessDump"), flashProcessType);
mCrashReporter->AddNote(NS_LITERAL_CSTRING("FlashProcessDump"), flashProcessType);
}
crashReporter->GenerateCrashReportForMinidump(dumpFile, &notes);
mCrashReporter->FinalizeCrashReport();
}
#endif
@ -1672,8 +1672,18 @@ PluginModuleParent::NotifyPluginCrashed()
return;
}
if (mPlugin)
mPlugin->PluginCrashed(mPluginDumpID, mBrowserDumpID);
if (!mPlugin) {
return;
}
nsString dumpID;
nsString browserDumpID;
#ifdef MOZ_CRASHREPORTER
if (mCrashReporter && mCrashReporter->HasMinidump()) {
dumpID = mCrashReporter->MinidumpID();
}
#endif
mPlugin->PluginCrashed(dumpID, browserDumpID);
}
PPluginInstanceParent*
@ -2988,45 +2998,6 @@ PluginModuleParent::RecvPluginHideWindow(const uint32_t& aWindowId)
#endif
}
PCrashReporterParent*
PluginModuleParent::AllocPCrashReporterParent(mozilla::dom::NativeThreadId* id,
uint32_t* processType)
{
MOZ_CRASH("unreachable");
}
bool
PluginModuleParent::DeallocPCrashReporterParent(PCrashReporterParent* actor)
{
MOZ_CRASH("unreachable");
}
PCrashReporterParent*
PluginModuleChromeParent::AllocPCrashReporterParent(mozilla::dom::NativeThreadId* id,
uint32_t* processType)
{
#ifdef MOZ_CRASHREPORTER
return new CrashReporterParent();
#else
return nullptr;
#endif
}
bool
PluginModuleChromeParent::DeallocPCrashReporterParent(PCrashReporterParent* actor)
{
#ifdef MOZ_CRASHREPORTER
#ifdef XP_WIN
mozilla::MutexAutoLock lock(mCrashReporterMutex);
if (actor == static_cast<PCrashReporterParent*>(mCrashReporter)) {
mCrashReporter = nullptr;
}
#endif
#endif
delete actor;
return true;
}
mozilla::ipc::IPCResult
PluginModuleParent::RecvSetCursor(const NSCursorInfo& aCursorInfo)
{

Просмотреть файл

@ -37,11 +37,10 @@ namespace mozilla {
#ifdef MOZ_GECKO_PROFILER
class ProfileGatherer;
#endif
namespace dom {
class PCrashReporterParent;
class CrashReporterParent;
} // namespace dom
namespace ipc {
class CrashReporterHost;
} // namespace ipc
namespace layers {
class TextureClientRecycleAllocator;
} // namespace layers
@ -86,8 +85,6 @@ class PluginModuleParent
{
protected:
typedef mozilla::PluginLibrary PluginLibrary;
typedef mozilla::dom::PCrashReporterParent PCrashReporterParent;
typedef mozilla::dom::CrashReporterParent CrashReporterParent;
PPluginInstanceParent*
AllocPPluginInstanceParent(const nsCString& aMimeType,
@ -168,12 +165,6 @@ protected:
virtual mozilla::ipc::IPCResult
RecvPluginHideWindow(const uint32_t& aWindowId) override;
virtual PCrashReporterParent*
AllocPCrashReporterParent(mozilla::dom::NativeThreadId* id,
uint32_t* processType) override;
virtual bool
DeallocPCrashReporterParent(PCrashReporterParent* actor) override;
virtual mozilla::ipc::IPCResult
RecvSetCursor(const NSCursorInfo& aCursorInfo) override;
@ -339,8 +330,6 @@ protected:
NPPluginFuncs* mNPPIface;
nsNPAPIPlugin* mPlugin;
ipc::TaskFactory<PluginModuleParent> mTaskFactory;
nsString mPluginDumpID;
nsString mBrowserDumpID;
nsString mHangID;
RefPtr<nsIObserver> mProfilerObserver;
TimeDuration mTimeBlocked;
@ -358,7 +347,6 @@ protected:
bool
GetPluginDetails();
friend class mozilla::dom::CrashReporterParent;
friend class mozilla::plugins::PluginAsyncSurrogate;
bool mIsStartingAsync;
@ -370,6 +358,17 @@ protected:
RefPtr<layers::TextureClientRecycleAllocator> mTextureAllocatorForDirectBitmap;
RefPtr<layers::TextureClientRecycleAllocator> mTextureAllocatorForDXGISurface;
#ifdef MOZ_CRASHREPORTER
/**
* This mutex protects the crash reporter when the Plugin Hang UI event
* handler is executing off main thread. It is intended to protect both
* the mCrashReporter variable in addition to the CrashReporterHost object
* that mCrashReporter refers to.
*/
mozilla::Mutex mCrashReporterMutex;
UniquePtr<ipc::CrashReporterHost> mCrashReporter;
#endif // MOZ_CRASHREPORTER
};
class PluginModuleContentParent : public PluginModuleParent
@ -410,6 +409,7 @@ class PluginModuleChromeParent
: public PluginModuleParent
, public mozilla::HangMonitor::Annotator
{
friend class mozilla::ipc::CrashReporterHost;
public:
/**
* LoadModule
@ -526,15 +526,9 @@ private:
#ifdef MOZ_CRASHREPORTER
void ProcessFirstMinidump();
void WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes);
void WriteExtraDataForMinidump();
#endif
virtual PCrashReporterParent*
AllocPCrashReporterParent(mozilla::dom::NativeThreadId* id,
uint32_t* processType) override;
virtual bool
DeallocPCrashReporterParent(PCrashReporterParent* actor) override;
PluginProcessParent* Process() const { return mSubprocess; }
base::ProcessHandle ChildProcessHandle() { return mSubprocess->GetChildProcessHandle(); }
@ -555,8 +549,6 @@ private:
int32_t aSandboxLevel,
bool aAllowAsyncInit);
CrashReporterParent* CrashReporter();
void CleanupFromTimeout(const bool aByHangUI);
virtual void UpdatePluginTimeout() override;
@ -569,6 +561,8 @@ private:
void RegisterSettingsCallbacks();
void UnregisterSettingsCallbacks();
bool InitCrashReporter();
virtual mozilla::ipc::IPCResult RecvNotifyContentModuleDestroyed() override;
static void CachedSettingChanged(const char* aPref, void* aModule);
@ -596,17 +590,6 @@ private:
PluginHangUIParent *mHangUIParent;
bool mHangUIEnabled;
bool mIsTimerReset;
#ifdef MOZ_CRASHREPORTER
/**
* This mutex protects the crash reporter when the Plugin Hang UI event
* handler is executing off main thread. It is intended to protect both
* the mCrashReporter variable in addition to the CrashReporterParent object
* that mCrashReporter refers to.
*/
mozilla::Mutex mCrashReporterMutex;
CrashReporterParent* mCrashReporter;
#endif // MOZ_CRASHREPORTER
/**
* Launches the Plugin Hang UI.
@ -625,7 +608,6 @@ private:
FinishHangUI();
#endif
friend class mozilla::dom::CrashReporterParent;
friend class mozilla::plugins::PluginAsyncSurrogate;
#ifdef MOZ_CRASHREPORTER_INJECTOR

Просмотреть файл

@ -33,16 +33,33 @@ CrashReporterHost::CrashReporterHost(GeckoProcessType aProcessType,
bool
CrashReporterHost::GenerateCrashReport(base::ProcessId aPid)
{
RefPtr<nsIFile> crashDump;
if (!XRE_TakeMinidumpForChild(aPid, getter_AddRefs(crashDump), nullptr)) {
return false;
}
if (!CrashReporter::GetIDFromMinidump(crashDump, mDumpID)) {
if (!TakeCrashedChildMinidump(aPid, nullptr)) {
return false;
}
return FinalizeCrashReport();
}
RefPtr<nsIFile>
CrashReporterHost::TakeCrashedChildMinidump(base::ProcessId aPid, uint32_t* aOutSequence)
{
MOZ_ASSERT(!HasMinidump());
RefPtr<nsIFile> crashDump;
if (!XRE_TakeMinidumpForChild(aPid, getter_AddRefs(crashDump), aOutSequence)) {
return nullptr;
}
if (!AdoptMinidump(crashDump)) {
return nullptr;
}
return crashDump.get();
}
bool
CrashReporterHost::AdoptMinidump(nsIFile* aFile)
{
return CrashReporter::GetIDFromMinidump(aFile, mDumpID);
}
bool
CrashReporterHost::FinalizeCrashReport()
{
@ -73,11 +90,16 @@ CrashReporterHost::FinalizeCrashReport()
SprintfLiteral(startTime, "%lld", static_cast<long long>(mStartTime));
notes.Put(NS_LITERAL_CSTRING("StartupTime"), nsDependentCString(startTime));
CrashReporterMetadataShmem::ReadAppNotes(mShmem, &notes);
// We might not have shmem (for example, when running crashreporter tests).
if (mShmem.IsReadable()) {
CrashReporterMetadataShmem::ReadAppNotes(mShmem, &notes);
}
CrashReporter::AppendExtraData(mDumpID, mExtraNotes);
CrashReporter::AppendExtraData(mDumpID, notes);
NotifyCrashService(mProcessType, mDumpID, &notes);
// Use mExtraNotes, since NotifyCrashService looks for "PluginHang" which is
// set in the parent process.
NotifyCrashService(mProcessType, mDumpID, &mExtraNotes);
mFinalized = true;
return true;

Просмотреть файл

@ -36,11 +36,53 @@ public:
// the process has a minidump attached and we were able to generate a report.
bool GenerateCrashReport(base::ProcessId aPid);
// Given an existing minidump for a crashed child process, take ownership of
// it from IPDL. After this, FinalizeCrashReport may be called.
RefPtr<nsIFile> TakeCrashedChildMinidump(base::ProcessId aPid, uint32_t* aOutSequence);
// Replace the stored minidump with a new one. After this,
// FinalizeCrashReport may be called.
bool AdoptMinidump(nsIFile* aFile);
// If a minidump was already captured (e.g. via the hang reporter), this
// finalizes the existing report by attaching metadata and notifying the
// crash service.
bool FinalizeCrashReport();
// Generate a paired minidump. This does not take the crash report, as
// GenerateCrashReport does. After this, FinalizeCrashReport may be called.
//
// This calls TakeCrashedChildMinidump and FinalizeCrashReport.
template <typename Toplevel>
bool GenerateMinidumpAndPair(Toplevel* aToplevelProtocol,
nsIFile* aMinidumpToPair,
const nsACString& aPairName)
{
ScopedProcessHandle childHandle;
#ifdef XP_MACOSX
childHandle = aToplevelProtocol->Process()->GetChildTask();
#else
if (!base::OpenPrivilegedProcessHandle(aToplevelProtocol->OtherPid(),
&childHandle.rwget()))
{
NS_WARNING("Failed to open child process handle.");
return false;
}
#endif
nsCOMPtr<nsIFile> targetDump;
if (!CrashReporter::CreateMinidumpsAndPair(childHandle,
mThreadId,
aPairName,
aMinidumpToPair,
getter_AddRefs(targetDump)))
{
return false;
}
return CrashReporter::GetIDFromMinidump(targetDump, mDumpID);
}
// This is a static helper function to notify the crash service that a
// crash has occurred. When PCrashReporter is removed, we can make this
// a member function. This can be called from any thread, and if not