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
--- 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;