Bug 1379763 - Part 1: Add a bhr-thread-hang observer, r=mconley
authorMichael Layzell <michael@thelayzells.com>
Mon, 10 Jul 2017 17:46:28 -0400
changeset 419782 dbb7c080c1df9eebc5cb7417f2affba0abb0af37
parent 419781 795947f535e823454f4dcf400b8c004dfd9d09a2
child 419783 633c98dc992ff13168710725ea94a8ac49f6d48a
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmconley
bugs1379763
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1379763 - Part 1: Add a bhr-thread-hang observer, r=mconley MozReview-Commit-ID: 4g8VUjZBiYH
xpcom/threads/BackgroundHangMonitor.cpp
xpcom/threads/moz.build
xpcom/threads/nsIHangDetails.idl
--- a/xpcom/threads/BackgroundHangMonitor.cpp
+++ b/xpcom/threads/BackgroundHangMonitor.cpp
@@ -21,16 +21,17 @@
 #include "ThreadStackHelper.h"
 #include "nsIObserverService.h"
 #include "nsIObserver.h"
 #include "mozilla/Services.h"
 #include "nsThreadUtils.h"
 #include "nsXULAppAPI.h"
 #include "GeckoProfiler.h"
 #include "nsNetCID.h"
+#include "nsIHangDetails.h"
 
 #include <algorithm>
 
 // Activate BHR only for one every BHR_BETA_MOD users.
 // This is now 100% of Beta population for the Beta 45/46 e10s A/B trials
 // It can be scaled back again in the future
 #define BHR_BETA_MOD 1;
 
@@ -233,16 +234,37 @@ public:
 
   // Returns true if this thread is (or might be) shared between other
   // BackgroundHangMonitors for the monitored thread.
   bool IsShared() {
     return mThreadType == BackgroundHangMonitor::THREAD_SHARED;
   }
 };
 
+/**
+ * HangDetails is the concrete implementaion of nsIHangDetails, and contains the
+ * infromation which we want to expose to observers of the bhr-thread-hang
+ * observer notification.
+ */
+class HangDetails : public nsIHangDetails
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIHANGDETAILS
+
+  HangDetails(uint32_t aDuration, const nsACString& aName)
+    : mDuration(aDuration)
+    , mName(aName)
+    {}
+private:
+  virtual ~HangDetails() {}
+
+  uint32_t mDuration;
+  nsCString mName;
+};
 
 StaticRefPtr<BackgroundHangManager> BackgroundHangManager::sInstance;
 bool BackgroundHangManager::sDisabled = true;
 
 MOZ_THREAD_LOCAL(BackgroundHangThread*) BackgroundHangThread::sTlsKey;
 bool BackgroundHangThread::sTlsKeyInitialized;
 
 BackgroundHangManager::BackgroundHangManager()
@@ -592,16 +614,29 @@ BackgroundHangThread::ReportHang(PRInter
     if (newHistogram == *oldHistogram) {
       // New histogram matches old one
       oldHistogram->Add(aHangTime, Move(mAnnotations));
       return;
     }
   }
   newHistogram.Add(aHangTime, Move(mAnnotations));
 
+  // Notify any observers of the "bhr-thread-hang" topic that a thread has hung.
+  nsCString name;
+  name.AssignASCII(mStats.GetName());
+  SystemGroup::Dispatch("NotifyBHRHangObservers", TaskCategory::Other,
+                        NS_NewRunnableFunction("NotifyBHRHangObservers", [=] {
+    nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+    if (os) {
+      // NOTE: Make sure to construct this on the main thread.
+      nsCOMPtr<nsIHangDetails> hangDetails = new HangDetails(aHangTime, name);
+      os->NotifyObservers(hangDetails, "bhr-thread-hang", nullptr);
+    }
+  }));
+
   // Process the hang off-main thread. We record a reference to the runnable in
   // mProcessHangRunnables so we can abort this preprocessing and just submit
   // the message if the processing takes too long and our thread is going away.
   RefPtr<ProcessHangRunnable> processHang =
     new ProcessHangRunnable(mManager, this, Move(newHistogram), Move(mNativeHangStack));
   mProcessHangRunnables.insertFront(processHang);
 
   // Try to dispatch the runnable to the StreamTransportService threadpool. If
@@ -873,9 +908,25 @@ BackgroundHangMonitor::ThreadHangStatsIt
   if (!mThread) {
     return nullptr;
   }
   Telemetry::ThreadHangStats* stats = &mThread->mStats;
   mThread = mThread->getNext();
   return stats;
 }
 
+NS_IMETHODIMP
+HangDetails::GetDuration(uint32_t* aDuration)
+{
+  *aDuration = mDuration;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+HangDetails::GetThreadName(nsACString& aName)
+{
+  aName.Assign(mName);
+  return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS(HangDetails, nsIHangDetails)
+
 } // namespace mozilla
--- a/xpcom/threads/moz.build
+++ b/xpcom/threads/moz.build
@@ -2,16 +2,17 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPIDL_SOURCES += [
     'nsIEnvironment.idl',
     'nsIEventTarget.idl',
+    'nsIHangDetails.idl',
     'nsIIdlePeriod.idl',
     'nsINamed.idl',
     'nsIProcess.idl',
     'nsIRunnable.idl',
     'nsISerialEventTarget.idl',
     'nsISupportsPriority.idl',
     'nsIThread.idl',
     'nsIThreadInternal.idl',
new file mode 100644
--- /dev/null
+++ b/xpcom/threads/nsIHangDetails.idl
@@ -0,0 +1,25 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+/**
+ * A scriptable interface for getting information about a BHR detected hang.
+ * This is the type of the subject of the "bhr-thread-hang" observer topic.
+ */
+[scriptable, uuid(23d63fff-38d6-4003-9c57-2c90aca1180a)]
+interface nsIHangDetails : nsISupports
+{
+  /**
+   * The detected duration of the hang.
+   */
+  readonly attribute uint32_t duration;
+
+  /**
+   * The name of the thread which hung
+   */
+  readonly attribute ACString threadName;
+};
+