Bug 818307: Part 2 - Plugin Hang UI ChromeHang annotations; r=gfritzsche

This commit is contained in:
Aaron Klotz 2014-10-21 11:48:08 -06:00
Родитель 8f1189a221
Коммит 33625fe909
3 изменённых файлов: 113 добавлений и 41 удалений

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

@ -356,6 +356,7 @@ PluginHangUIParent::RecvUserResponse(const unsigned int& aResponse)
mModule->TerminateChildProcess(mMainThreadMessageLoop); mModule->TerminateChildProcess(mMainThreadMessageLoop);
responseCode = 1; responseCode = 1;
} else if(aResponse & HANGUI_USER_RESPONSE_CONTINUE) { } else if(aResponse & HANGUI_USER_RESPONSE_CONTINUE) {
mModule->OnHangUIContinue();
// User clicked Continue // User clicked Continue
responseCode = 2; responseCode = 2;
} else { } else {

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

@ -133,6 +133,7 @@ PluginModuleParent::PluginModuleParent(const char* aFilePath)
, mNPNIface(nullptr) , mNPNIface(nullptr)
, mPlugin(nullptr) , mPlugin(nullptr)
, mTaskFactory(MOZ_THIS_IN_INITIALIZER_LIST()) , mTaskFactory(MOZ_THIS_IN_INITIALIZER_LIST())
, mHangAnnotationFlags(0)
#ifdef XP_WIN #ifdef XP_WIN
, mPluginCpuUsageOnHang() , mPluginCpuUsageOnHang()
, mHangUIParent(nullptr) , mHangUIParent(nullptr)
@ -160,6 +161,8 @@ PluginModuleParent::PluginModuleParent(const char* aFilePath)
#ifdef MOZ_ENABLE_PROFILER_SPS #ifdef MOZ_ENABLE_PROFILER_SPS
InitPluginProfiling(); InitPluginProfiling();
#endif #endif
mozilla::HangMonitor::RegisterAnnotator(*this);
} }
PluginModuleParent::~PluginModuleParent() PluginModuleParent::~PluginModuleParent()
@ -203,6 +206,8 @@ PluginModuleParent::~PluginModuleParent()
mHangUIParent = nullptr; mHangUIParent = nullptr;
} }
#endif #endif
mozilla::HangMonitor::UnregisterAnnotator(*this);
} }
#ifdef MOZ_CRASHREPORTER #ifdef MOZ_CRASHREPORTER
@ -224,20 +229,8 @@ PluginModuleParent::WriteExtraDataForMinidump(AnnotationTable& notes)
filePos++; filePos++;
notes.Put(NS_LITERAL_CSTRING("PluginFilename"), CS(pluginFile.substr(filePos).c_str())); notes.Put(NS_LITERAL_CSTRING("PluginFilename"), CS(pluginFile.substr(filePos).c_str()));
nsCString pluginName; notes.Put(NS_LITERAL_CSTRING("PluginName"), mPluginName);
nsCString pluginVersion; notes.Put(NS_LITERAL_CSTRING("PluginVersion"), mPluginVersion);
nsRefPtr<nsPluginHost> ph = nsPluginHost::GetInst();
if (ph) {
nsPluginTag* tag = ph->TagForPlugin(mPlugin);
if (tag) {
pluginName = tag->mName;
pluginVersion = tag->mVersion;
}
}
notes.Put(NS_LITERAL_CSTRING("PluginName"), pluginName);
notes.Put(NS_LITERAL_CSTRING("PluginVersion"), pluginVersion);
CrashReporterParent* crashReporter = CrashReporter(); CrashReporterParent* crashReporter = CrashReporter();
if (crashReporter) { if (crashReporter) {
@ -389,13 +382,52 @@ GetProcessCpuUsage(const InfallibleTArray<base::ProcessHandle>& processHandles,
} // anonymous namespace } // anonymous namespace
#endif // #ifdef XP_WIN
void
PluginModuleParent::EnteredCxxStack()
{
mHangAnnotationFlags |= kInPluginCall;
}
void void
PluginModuleParent::ExitedCxxStack() PluginModuleParent::ExitedCxxStack()
{ {
mHangAnnotationFlags = 0;
#ifdef XP_WIN
FinishHangUI(); FinishHangUI();
#endif
} }
#endif // #ifdef XP_WIN /**
* This function is always called by the HangMonitor thread.
*/
void
PluginModuleParent::AnnotateHang(mozilla::HangMonitor::HangAnnotations& aAnnotations)
{
uint32_t flags = mHangAnnotationFlags;
if (flags) {
/* We don't actually annotate anything specifically for kInPluginCall;
we use it to determine whether to annotate other things. It will
be pretty obvious from the ChromeHang stack that we're in a plugin
call when the hang occurred. */
if (flags & kHangUIShown) {
aAnnotations.AddAnnotation(NS_LITERAL_STRING("HangUIShown"),
true);
}
if (flags & kHangUIContinued) {
aAnnotations.AddAnnotation(NS_LITERAL_STRING("HangUIContinued"),
true);
}
if (flags & kHangUIDontShow) {
aAnnotations.AddAnnotation(NS_LITERAL_STRING("HangUIDontShow"),
true);
}
aAnnotations.AddAnnotation(NS_LITERAL_STRING("pluginName"), mPluginName);
aAnnotations.AddAnnotation(NS_LITERAL_STRING("pluginVersion"),
mPluginVersion);
}
}
#ifdef MOZ_CRASHREPORTER_INJECTOR #ifdef MOZ_CRASHREPORTER_INJECTOR
static bool static bool
@ -531,6 +563,23 @@ PluginModuleParent::TerminateChildProcess(MessageLoop* aMsgLoop)
NS_WARNING("failed to kill subprocess!"); NS_WARNING("failed to kill subprocess!");
} }
bool
PluginModuleParent::GetPluginDetails(nsACString& aPluginName,
nsACString& aPluginVersion)
{
nsRefPtr<nsPluginHost> host = nsPluginHost::GetInst();
if (!host) {
return false;
}
nsPluginTag* pluginTag = host->TagForPlugin(mPlugin);
if (!pluginTag) {
return false;
}
aPluginName = pluginTag->mName;
aPluginVersion = pluginTag->mVersion;
return true;
}
#ifdef XP_WIN #ifdef XP_WIN
void void
PluginModuleParent::EvaluateHangUIState(const bool aReset) PluginModuleParent::EvaluateHangUIState(const bool aReset)
@ -566,21 +615,6 @@ PluginModuleParent::EvaluateHangUIState(const bool aReset)
SetChildTimeout(autoStopSecs); SetChildTimeout(autoStopSecs);
} }
bool
PluginModuleParent::GetPluginName(nsAString& aPluginName)
{
nsRefPtr<nsPluginHost> host = nsPluginHost::GetInst();
if (!host) {
return false;
}
nsPluginTag* pluginTag = host->TagForPlugin(mPlugin);
if (!pluginTag) {
return false;
}
CopyUTF8toUTF16(pluginTag->mName, aPluginName);
return true;
}
bool bool
PluginModuleParent::LaunchHangUI() PluginModuleParent::LaunchHangUI()
{ {
@ -593,7 +627,12 @@ PluginModuleParent::LaunchHangUI()
return false; return false;
} }
if (mHangUIParent->DontShowAgain()) { if (mHangUIParent->DontShowAgain()) {
return !mHangUIParent->WasLastHangStopped(); mHangAnnotationFlags |= kHangUIDontShow;
bool wasLastHangStopped = mHangUIParent->WasLastHangStopped();
if (!wasLastHangStopped) {
mHangAnnotationFlags |= kHangUIContinued;
}
return !wasLastHangStopped;
} }
delete mHangUIParent; delete mHangUIParent;
mHangUIParent = nullptr; mHangUIParent = nullptr;
@ -601,12 +640,9 @@ PluginModuleParent::LaunchHangUI()
mHangUIParent = new PluginHangUIParent(this, mHangUIParent = new PluginHangUIParent(this,
Preferences::GetInt(kHangUITimeoutPref, 0), Preferences::GetInt(kHangUITimeoutPref, 0),
Preferences::GetInt(kChildTimeoutPref, 0)); Preferences::GetInt(kChildTimeoutPref, 0));
nsAutoString pluginName; bool retval = mHangUIParent->Init(NS_ConvertUTF8toUTF16(mPluginName));
if (!GetPluginName(pluginName)) {
return false;
}
bool retval = mHangUIParent->Init(pluginName);
if (retval) { if (retval) {
mHangAnnotationFlags |= kHangUIShown;
/* Once the UI is shown we switch the timeout over to use /* Once the UI is shown we switch the timeout over to use
kChildTimeoutPref, allowing us to terminate a hung plugin kChildTimeoutPref, allowing us to terminate a hung plugin
after kChildTimeoutPref seconds if the user doesn't respond to after kChildTimeoutPref seconds if the user doesn't respond to
@ -636,6 +672,12 @@ PluginModuleParent::FinishHangUI()
} }
} }
} }
void
PluginModuleParent::OnHangUIContinue()
{
mHangAnnotationFlags |= kHangUIContinued;
}
#endif // XP_WIN #endif // XP_WIN
#ifdef MOZ_CRASHREPORTER #ifdef MOZ_CRASHREPORTER
@ -1263,6 +1305,10 @@ PluginModuleParent::NPP_New(NPMIMEType pluginType, NPP instance,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
if (mPluginName.IsEmpty()) {
GetPluginDetails(mPluginName, mPluginVersion);
}
// create the instance on the other side // create the instance on the other side
InfallibleTArray<nsCString> names; InfallibleTArray<nsCString> names;
InfallibleTArray<nsCString> values; InfallibleTArray<nsCString> values;

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

@ -9,6 +9,7 @@
#include "base/process.h" #include "base/process.h"
#include "mozilla/FileUtils.h" #include "mozilla/FileUtils.h"
#include "mozilla/HangMonitor.h"
#include "mozilla/PluginLibrary.h" #include "mozilla/PluginLibrary.h"
#include "mozilla/plugins/ScopedMethodFactory.h" #include "mozilla/plugins/ScopedMethodFactory.h"
#include "mozilla/plugins/PluginProcessParent.h" #include "mozilla/plugins/PluginProcessParent.h"
@ -59,6 +60,7 @@ class PluginModuleParent
#ifdef MOZ_CRASHREPORTER_INJECTOR #ifdef MOZ_CRASHREPORTER_INJECTOR
, public CrashReporter::InjectorCrashCallback , public CrashReporter::InjectorCrashCallback
#endif #endif
, public mozilla::HangMonitor::Annotator
{ {
private: private:
typedef mozilla::PluginLibrary PluginLibrary; typedef mozilla::PluginLibrary PluginLibrary;
@ -112,9 +114,22 @@ public:
void TerminateChildProcess(MessageLoop* aMsgLoop); void TerminateChildProcess(MessageLoop* aMsgLoop);
#ifdef XP_WIN virtual void
void EnteredCxxStack() MOZ_OVERRIDE;
virtual void
ExitedCxxStack() MOZ_OVERRIDE; ExitedCxxStack() MOZ_OVERRIDE;
virtual void
AnnotateHang(mozilla::HangMonitor::HangAnnotations& aAnnotations) MOZ_OVERRIDE;
#ifdef XP_WIN
/**
* Called by Plugin Hang UI to notify that the user has clicked continue.
* Used for chrome hang annotations.
*/
void
OnHangUIContinue();
#endif // XP_WIN #endif // XP_WIN
protected: protected:
@ -287,6 +302,16 @@ private:
nsString mBrowserDumpID; nsString mBrowserDumpID;
nsString mHangID; nsString mHangID;
nsRefPtr<nsIObserver> mProfilerObserver; nsRefPtr<nsIObserver> mProfilerObserver;
enum HangAnnotationFlags
{
kInPluginCall = (1u << 0),
kHangUIShown = (1u << 1),
kHangUIContinued = (1u << 2),
kHangUIDontShow = (1u << 3)
};
Atomic<uint32_t> mHangAnnotationFlags;
nsCString mPluginName;
nsCString mPluginVersion;
#ifdef XP_WIN #ifdef XP_WIN
InfallibleTArray<float> mPluginCpuUsageOnHang; InfallibleTArray<float> mPluginCpuUsageOnHang;
PluginHangUIParent *mHangUIParent; PluginHangUIParent *mHangUIParent;
@ -307,9 +332,6 @@ private:
void void
EvaluateHangUIState(const bool aReset); EvaluateHangUIState(const bool aReset);
bool
GetPluginName(nsAString& aPluginName);
/** /**
* Launches the Plugin Hang UI. * Launches the Plugin Hang UI.
* *
@ -327,6 +349,9 @@ private:
FinishHangUI(); FinishHangUI();
#endif #endif
bool
GetPluginDetails(nsACString& aPluginName, nsACString& aPluginVersion);
#ifdef MOZ_X11 #ifdef MOZ_X11
// Dup of plugin's X socket, used to scope its resources to this // Dup of plugin's X socket, used to scope its resources to this
// object instead of the plugin process's lifetime // object instead of the plugin process's lifetime