Bug 1384238 - Annotate BHR hangs which occur while there is a pending input event, r=smaug

MozReview-Commit-ID: HRPMw2IfEKB
This commit is contained in:
Michael Layzell
2017-08-09 16:59:27 -04:00
parent ab871b0fef
commit 1f743a917c
5 changed files with 118 additions and 17 deletions

View File

@@ -10686,6 +10686,29 @@ nsContentUtils::GetSourceMapURL(nsIHttpChannel* aChannel, nsACString& aResult)
return NS_SUCCEEDED(rv);
}
/* static */ bool
nsContentUtils::IsMessageInputEvent(const IPC::Message& aMsg)
{
if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart)
== mozilla::dom::PBrowser::PBrowserStart) {
switch (aMsg.type()) {
case mozilla::dom::PBrowser::Msg_RealMouseMoveEvent__ID:
case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID:
case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID:
case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID:
case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID:
case mozilla::dom::PBrowser::Msg_RealTouchMoveEvent__ID:
case mozilla::dom::PBrowser::Msg_RealDragEvent__ID:
case mozilla::dom::PBrowser::Msg_UpdateDimensions__ID:
case mozilla::dom::PBrowser::Msg_MouseEvent__ID:
case mozilla::dom::PBrowser::Msg_KeyEvent__ID:
case mozilla::dom::PBrowser::Msg_SetDocShellIsActive__ID:
return true;
}
}
return false;
}
static const char* kUserInteractionInactive = "user-interaction-inactive";
static const char* kUserInteractionActive = "user-interaction-active";

View File

@@ -3126,6 +3126,13 @@ public:
*/
static bool GetSourceMapURL(nsIHttpChannel* aChannel, nsACString& aResult);
/**
* Returns true if the passed-in mesasge is a pending InputEvent.
*
* @param aMsg The message to check
*/
static bool IsMessageInputEvent(const IPC::Message& aMsg);
private:
static bool InitializeEventTable();

View File

@@ -491,6 +491,29 @@ private:
}
};
#ifdef NIGHTLY_BUILD
/**
* The singleton of this class is registered with the HangMonitor as an
* annotator, so that the hang monitor can record whether or not there were
* pending input events when the thread hung.
*/
class PendingInputEventHangAnnotator final
: public HangMonitor::Annotator
{
public:
virtual void AnnotateHang(HangMonitor::HangAnnotations& aAnnotations)
{
int32_t pending = ContentChild::GetSingleton()->GetPendingInputEvents();
if (pending > 0) {
aAnnotations.AddAnnotation(NS_LITERAL_STRING("PendingInput"), pending);
}
}
static PendingInputEventHangAnnotator sSingleton;
};
PendingInputEventHangAnnotator PendingInputEventHangAnnotator::sSingleton;
#endif
NS_IMPL_ISUPPORTS(BackgroundChildPrimer, nsIIPCBackgroundChildCreateCallback)
ContentChild* ContentChild::sSingleton;
@@ -638,6 +661,10 @@ ContentChild::Init(MessageLoop* aIOLoop,
SetProcessName(NS_LITERAL_STRING("Web Content"));
#ifdef NIGHTLY_BUILD
HangMonitor::RegisterAnnotator(PendingInputEventHangAnnotator::sSingleton);
#endif
return true;
}
@@ -2930,6 +2957,10 @@ ContentChild::RecvShutdown()
mShuttingDown = true;
#ifdef NIGHTLY_BUILD
HangMonitor::UnregisterAnnotator(PendingInputEventHangAnnotator::sSingleton);
#endif
if (mPolicy) {
mPolicy->Deactivate();
mPolicy = nullptr;
@@ -3580,6 +3611,33 @@ ContentChild::GetSpecificMessageEventTarget(const Message& aMsg)
return nullptr;
}
#ifdef NIGHTLY_BUILD
void
ContentChild::OnChannelReceivedMessage(const Message& aMsg)
{
if (nsContentUtils::IsMessageInputEvent(aMsg)) {
mPendingInputEvents++;
}
}
PContentChild::Result
ContentChild::OnMessageReceived(const Message& aMsg)
{
if (nsContentUtils::IsMessageInputEvent(aMsg)) {
DebugOnly<uint32_t> prevEvts = mPendingInputEvents--;
MOZ_ASSERT(prevEvts > 0);
}
return PContentChild::OnMessageReceived(aMsg);
}
PContentChild::Result
ContentChild::OnMessageReceived(const Message& aMsg, Message*& aReply)
{
return PContentChild::OnMessageReceived(aMsg, aReply);
}
#endif
} // namespace dom
#if !defined(XP_WIN)

View File

@@ -681,6 +681,17 @@ public:
nsTArray<PluginTag>&& aPluginTags,
nsTArray<FakePluginTag>&& aFakePluginTags) override;
#ifdef NIGHTLY_BUILD
// Fetch the current number of pending input events.
//
// NOTE: This method performs an atomic read, and is safe to call from all threads.
uint32_t
GetPendingInputEvents()
{
return mPendingInputEvents;
}
#endif
private:
static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure);
void StartForceKillTimer();
@@ -695,6 +706,17 @@ private:
virtual already_AddRefed<nsIEventTarget>
GetSpecificMessageEventTarget(const Message& aMsg) override;
#ifdef NIGHTLY_BUILD
virtual void
OnChannelReceivedMessage(const Message& aMsg) override;
virtual PContentChild::Result
OnMessageReceived(const Message& aMsg) override;
virtual PContentChild::Result
OnMessageReceived(const Message& aMsg, Message*& aReply) override;
#endif
InfallibleTArray<nsAutoPtr<AlertObserver> > mAlertObservers;
RefPtr<ConsoleListener> mConsoleListener;
@@ -765,6 +787,11 @@ private:
mozilla::Atomic<bool> mShuttingDown;
#ifdef NIGHTLY_BUILD
// NOTE: This member is atomic because it can be accessed from off-main-thread.
mozilla::Atomic<uint32_t> mPendingInputEvents;
#endif
DISALLOW_EVIL_CONSTRUCTORS(ContentChild);
};

View File

@@ -1404,24 +1404,10 @@ PuppetWidget::HasPendingInputEvent()
mTabChild->GetIPCChannel()->PeekMessages(
[&ret](const IPC::Message& aMsg) -> bool {
if ((aMsg.type() & mozilla::dom::PBrowser::PBrowserStart)
== mozilla::dom::PBrowser::PBrowserStart) {
switch (aMsg.type()) {
case mozilla::dom::PBrowser::Msg_RealMouseMoveEvent__ID:
case mozilla::dom::PBrowser::Msg_RealMouseButtonEvent__ID:
case mozilla::dom::PBrowser::Msg_RealKeyEvent__ID:
case mozilla::dom::PBrowser::Msg_MouseWheelEvent__ID:
case mozilla::dom::PBrowser::Msg_RealTouchEvent__ID:
case mozilla::dom::PBrowser::Msg_RealTouchMoveEvent__ID:
case mozilla::dom::PBrowser::Msg_RealDragEvent__ID:
case mozilla::dom::PBrowser::Msg_UpdateDimensions__ID:
case mozilla::dom::PBrowser::Msg_MouseEvent__ID:
case mozilla::dom::PBrowser::Msg_KeyEvent__ID:
case mozilla::dom::PBrowser::Msg_SetDocShellIsActive__ID:
if (nsContentUtils::IsMessageInputEvent(aMsg)) {
ret = true;
return false; // Stop peeking.
}
}
return true;
}
);