Bug 1358583 - Handle NS_DispatchToMainThread failures gracefully. r?njn draft
authorMarkus Stange <mstange@themasta.com>
Wed, 10 May 2017 17:05:00 -0400
changeset 575782 cb9739e2b1c50d579b7620c7d59c34fd3c62f3b4
parent 575780 0b19326cb7c45b3c3f561e42bc5722ecdfec1c08
child 575783 63295ae352ae7b918fe1703c3140774b16034587
push id58165
push userbmo:mstange@themasta.com
push dateWed, 10 May 2017 21:05:21 +0000
reviewersnjn
bugs1358583
milestone55.0a1
Bug 1358583 - Handle NS_DispatchToMainThread failures gracefully. r?njn MozReview-Commit-ID: GP1yC1CL9GA
tools/profiler/gecko/ThreadResponsiveness.cpp
--- a/tools/profiler/gecko/ThreadResponsiveness.cpp
+++ b/tools/profiler/gecko/ThreadResponsiveness.cpp
@@ -16,27 +16,45 @@ using mozilla::TimeStamp;
 
 class CheckResponsivenessTask : public mozilla::Runnable,
                                 public nsITimerCallback {
 public:
   CheckResponsivenessTask()
     : mLastTracerTime(TimeStamp::Now())
     , mMonitor("CheckResponsivenessTask")
     , mTimer(nullptr)
+    , mHasEverBeenSuccessfullyDispatched(false)
     , mStop(false)
   {
   }
 
 protected:
   ~CheckResponsivenessTask()
   {
   }
 
 public:
 
+  // Must be called from the same thread every time. Call that the "update"
+  // thread, because it's the thread that ThreadResponsiveness::Update() is
+  // called on. In reality it's the profiler's sampler thread.
+  void DoFirstDispatchIfNeeded()
+  {
+    if (mHasEverBeenSuccessfullyDispatched) {
+      return;
+    }
+
+    // Dispatching can fail during early startup, particularly when
+    // MOZ_PROFILER_STARTUP is used.
+    nsresult rv = NS_DispatchToMainThread(this);
+    if (NS_SUCCEEDED(rv)) {
+      mHasEverBeenSuccessfullyDispatched = true;
+    }
+  }
+
   // Can only run on the main thread.
   NS_IMETHOD Run() override
   {
     MonitorAutoLock mon(mMonitor);
     if (mStop)
       return NS_OK;
 
     // This is raced on because we might pause the thread here
@@ -69,39 +87,34 @@ public:
   }
 
   NS_DECL_ISUPPORTS_INHERITED
 
 private:
   TimeStamp mLastTracerTime;
   Monitor mMonitor;
   nsCOMPtr<nsITimer> mTimer;
+  bool mHasEverBeenSuccessfullyDispatched; // only accessed on the "update" thread
   bool mStop;
 };
 
 NS_IMPL_ISUPPORTS_INHERITED(CheckResponsivenessTask, mozilla::Runnable,
                             nsITimerCallback)
 
 ThreadResponsiveness::ThreadResponsiveness()
-  : mActiveTracerEvent(nullptr)
+  : mActiveTracerEvent(new CheckResponsivenessTask())
 {
   MOZ_COUNT_CTOR(ThreadResponsiveness);
 }
 
 ThreadResponsiveness::~ThreadResponsiveness()
 {
   MOZ_COUNT_DTOR(ThreadResponsiveness);
-  if (mActiveTracerEvent) {
-    mActiveTracerEvent->Terminate();
-  }
+  mActiveTracerEvent->Terminate();
 }
 
 void
 ThreadResponsiveness::Update()
 {
-  if (!mActiveTracerEvent) {
-    mActiveTracerEvent = new CheckResponsivenessTask();
-    NS_DispatchToMainThread(mActiveTracerEvent);
-  }
-
+  mActiveTracerEvent->DoFirstDispatchIfNeeded();
   mLastTracerTime = mActiveTracerEvent->GetLastTracerTime();
 }