Bug 1262852 - Create a minidump of the plugin process as soon as possible during hang r=jimm

This commit is contained in:
Gabriele Svelto
2016-06-24 14:25:08 +02:00
parent a8774d9a5f
commit f8555cd1cf
4 changed files with 147 additions and 54 deletions

View File

@@ -353,26 +353,50 @@ bool PluginModuleMapping::sIsLoadModuleOnStack = false;
} // namespace
static PluginModuleChromeParent*
PluginModuleChromeParentForId(const uint32_t aPluginId)
{
MOZ_ASSERT(XRE_IsParentProcess());
RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
nsPluginTag* pluginTag = host->PluginWithId(aPluginId);
if (!pluginTag || !pluginTag->mPlugin) {
return nullptr;
}
RefPtr<nsNPAPIPlugin> plugin = pluginTag->mPlugin;
return static_cast<PluginModuleChromeParent*>(plugin->GetLibrary());
}
void
mozilla::plugins::TakeFullMinidump(uint32_t aPluginId,
base::ProcessId aContentProcessId,
const nsAString& aBrowserDumpId,
nsString& aDumpId)
{
PluginModuleChromeParent* chromeParent =
PluginModuleChromeParentForId(aPluginId);
if (chromeParent) {
chromeParent->TakeFullMinidump(aContentProcessId, aBrowserDumpId, aDumpId);
}
}
void
mozilla::plugins::TerminatePlugin(uint32_t aPluginId,
base::ProcessId aContentProcessId,
const nsCString& aMonitorDescription,
const nsAString& aBrowserDumpId)
const nsAString& aDumpId)
{
MOZ_ASSERT(XRE_IsParentProcess());
PluginModuleChromeParent* chromeParent =
PluginModuleChromeParentForId(aPluginId);
RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
nsPluginTag* pluginTag = host->PluginWithId(aPluginId);
if (!pluginTag || !pluginTag->mPlugin) {
return;
}
RefPtr<nsNPAPIPlugin> plugin = pluginTag->mPlugin;
PluginModuleChromeParent* chromeParent =
static_cast<PluginModuleChromeParent*>(plugin->GetLibrary());
if (chromeParent) {
chromeParent->TerminateChildProcess(MessageLoop::current(),
aContentProcessId,
aMonitorDescription,
aBrowserDumpId);
aDumpId);
}
}
/* static */ PluginLibrary*
@@ -1198,38 +1222,19 @@ PluginModuleContentParent::OnExitedSyncSend()
}
void
PluginModuleChromeParent::TerminateChildProcess(MessageLoop* aMsgLoop,
base::ProcessId aContentPid,
const nsCString& aMonitorDescription,
const nsAString& aBrowserDumpId)
PluginModuleChromeParent::TakeFullMinidump(base::ProcessId aContentPid,
const nsAString& aBrowserDumpId,
nsString& aDumpId)
{
#ifdef MOZ_CRASHREPORTER
#ifdef XP_WIN
mozilla::MutexAutoLock lock(mCrashReporterMutex);
CrashReporterParent* crashReporter = mCrashReporter;
#endif // XP_WIN
CrashReporterParent* crashReporter = CrashReporter();
if (!crashReporter) {
// 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
crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("PluginHang"),
NS_LITERAL_CSTRING("1"));
crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("HangMonitorDescription"),
aMonitorDescription);
#ifdef XP_WIN
if (mHangUIParent) {
unsigned int hangUIDuration = mHangUIParent->LastShowDurationMs();
if (hangUIDuration) {
nsPrintfCString strHangUIDuration("%u", hangUIDuration);
crashReporter->AnnotateCrashReport(
NS_LITERAL_CSTRING("PluginHangUIDuration"),
strHangUIDuration);
}
}
#endif // XP_WIN
bool reportsReady = false;
@@ -1266,6 +1271,7 @@ PluginModuleChromeParent::TerminateChildProcess(MessageLoop* aMsgLoop,
// 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;
PLUGIN_LOG_DEBUG(
("generated paired browser/plugin minidumps: %s)",
NS_ConvertUTF16toUTF8(mPluginDumpID).get()));
@@ -1284,7 +1290,7 @@ PluginModuleChromeParent::TerminateChildProcess(MessageLoop* aMsgLoop,
NS_LITERAL_CSTRING("flash2"))) {
additionalDumps.AppendLiteral(",flash2");
}
#endif
#endif // MOZ_CRASHREPORTER_INJECTOR
if (aContentPid != mozilla::ipc::kInvalidProcessId) {
// Include the content process minidump
if (CreatePluginMinidump(aContentPid, 0,
@@ -1300,7 +1306,51 @@ PluginModuleChromeParent::TerminateChildProcess(MessageLoop* aMsgLoop,
} else {
NS_WARNING("failed to capture paired minidumps from hang");
}
#endif
#endif // MOZ_CRASHREPORTER
}
void
PluginModuleChromeParent::TerminateChildProcess(MessageLoop* aMsgLoop,
base::ProcessId aContentPid,
const nsCString& aMonitorDescription,
const nsAString& aDumpId)
{
#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.
nsAutoString dumpId;
if (aDumpId.IsEmpty()) {
TakeFullMinidump(aContentPid, EmptyString(), dumpId);
}
#ifdef XP_WIN
mozilla::MutexAutoLock lock(mCrashReporterMutex);
CrashReporterParent* crashReporter = mCrashReporter;
if (!crashReporter) {
// 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);
#ifdef XP_WIN
if (mHangUIParent) {
unsigned int hangUIDuration = mHangUIParent->LastShowDurationMs();
if (hangUIDuration) {
nsPrintfCString strHangUIDuration("%u", hangUIDuration);
crashReporter->AnnotateCrashReport(
NS_LITERAL_CSTRING("PluginHangUIDuration"),
strHangUIDuration);
}
}
#endif // XP_WIN
#endif // MOZ_CRASHREPORTER
mozilla::ipc::ScopedProcessHandle geckoChildProcess;
bool childOpened = base::OpenProcessHandle(OtherPid(),