bug 1304660 - Don't dispatch to main once xpcom starts shutting down. r=froydnj
authorChris H-C <chutten@mozilla.com>
Wed, 28 Sep 2016 14:44:35 -0400
changeset 315799 51199a9bdf29e063ddce5ce36db6bdd9ada10014
parent 315798 b974a64f96bc986f139fc388feff4509fb59f264
child 315800 dcd89f87bf8601e6c40f2a361edc92c5d95b15e8
push id20634
push usercbook@mozilla.com
push dateFri, 30 Sep 2016 10:10:13 +0000
treeherderfx-team@afe79b010d13 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1304660
milestone52.0a1
bug 1304660 - Don't dispatch to main once xpcom starts shutting down. r=froydnj If we manage to dispatch to main after xpcom shutdown, the main thread won't care for our new runnable and leak it. MozReview-Commit-ID: 8t4hOgfgEeP
toolkit/components/telemetry/TelemetryHistogram.cpp
--- a/toolkit/components/telemetry/TelemetryHistogram.cpp
+++ b/toolkit/components/telemetry/TelemetryHistogram.cpp
@@ -195,16 +195,19 @@ base::StatisticsRecorder* gStatisticsRec
 
 // For batching and sending child process accumulations to the parent
 nsITimer* gIPCTimer = nullptr;
 mozilla::Atomic<bool, mozilla::Relaxed> gIPCTimerArmed(false);
 mozilla::Atomic<bool, mozilla::Relaxed> gIPCTimerArming(false);
 StaticAutoPtr<nsTArray<Accumulation>> gAccumulations;
 StaticAutoPtr<nsTArray<KeyedAccumulation>> gKeyedAccumulations;
 
+// Has XPCOM started shutting down?
+mozilla::Atomic<bool, mozilla::Relaxed>  gShuttingDown(false);
+
 } // namespace
 
 
 ////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////
 //
 // PRIVATE CONSTANTS
 
@@ -342,16 +345,37 @@ StringEndsWith(const std::string& name, 
 {
   if (name.size() < suffix.size()) {
     return false;
   }
 
   return name.compare(name.size() - suffix.size(), suffix.size(), suffix) == 0;
 }
 
+struct TelemetryShutdownObserver : public nsIObserver
+{
+  NS_DECL_ISUPPORTS
+
+  NS_IMETHOD Observe(nsISupports*, const char* aTopic, const char16_t*) override
+  {
+    if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) != 0) {
+      return NS_OK;
+    }
+    nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+    if (obs) {
+      obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
+    }
+    gShuttingDown = true;
+    return NS_OK;
+  }
+private:
+  virtual ~TelemetryShutdownObserver() { }
+};
+NS_IMPL_ISUPPORTS(TelemetryShutdownObserver, nsIObserver)
+
 } // namespace
 
 
 ////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////
 //
 // PRIVATE: Histogram Get, Add, Clone, Clear functions
 
@@ -1298,17 +1322,17 @@ void internal_armIPCTimerMainThread()
 void internal_armIPCTimer()
 {
   if (gIPCTimerArmed || gIPCTimerArming) {
     return;
   }
   gIPCTimerArming = true;
   if (NS_IsMainThread()) {
     internal_armIPCTimerMainThread();
-  } else {
+  } else if (!gShuttingDown) {
     NS_DispatchToMainThread(NS_NewRunnableFunction([]() -> void {
       StaticMutexAutoLock locker(gTelemetryHistogramMutex);
       internal_armIPCTimerMainThread();
     }));
   }
 }
 
 bool
@@ -2018,16 +2042,20 @@ void TelemetryHistogram::InitializeGloba
       "and update the n_values for the following in Histograms.json: "
       "GC_MINOR_REASON, GC_MINOR_REASON_LONG, GC_REASON_2");
   static_assert((mozilla::StartupTimeline::MAX_EVENT_ID == 16),
       "MAX_EVENT_ID is assumed to be a fixed value in Histograms.json.  If this"
       " was an intentional change, update this assert with its value and update"
       " the n_values for the following in Histograms.json:"
       " STARTUP_MEASUREMENT_ERRORS");
 
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+  MOZ_ASSERT(obs);
+  obs->AddObserver(new TelemetryShutdownObserver, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
+
   gInitDone = true;
 }
 
 void TelemetryHistogram::DeInitializeGlobalState()
 {
   StaticMutexAutoLock locker(gTelemetryHistogramMutex);
   gCanRecordBase = false;
   gCanRecordExtended = false;