Bug 1146580 - Make FinalizationWitnessService listen for xpcom shutdown. r=bholley
authorEric Rahm <erahm@mozilla.com>
Wed, 10 Jun 2015 15:12:33 -0700
changeset 248186 179adcb0f8628c0adb037d3b5a2beb959a250e7b
parent 248185 7466fbbe72ac98cb5fe3046c913efe199ad19cda
child 248187 b3f90ab360afe8da2916d5fac83e2f2f1f01f1cf
push id28893
push userkwierso@gmail.com
push dateFri, 12 Jun 2015 00:02:58 +0000
treeherderautoland@8cf9d3e497f9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs1146580
milestone41.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 1146580 - Make FinalizationWitnessService listen for xpcom shutdown. r=bholley
toolkit/components/build/nsToolkitCompsModule.cpp
toolkit/components/finalizationwitness/FinalizationWitnessService.cpp
toolkit/components/finalizationwitness/FinalizationWitnessService.h
--- a/toolkit/components/build/nsToolkitCompsModule.cpp
+++ b/toolkit/components/build/nsToolkitCompsModule.cpp
@@ -115,17 +115,17 @@ nsUrlClassifierDBServiceConstructor(nsIS
     return rv;
 }
 #endif
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsBrowserStatusFilter)
 #if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsUpdateProcessor)
 #endif
-NS_GENERIC_FACTORY_CONSTRUCTOR(FinalizationWitnessService)
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(FinalizationWitnessService, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(NativeOSFileInternalsService)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(NativeFileWatcherService, Init)
 
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(AddonPathService, AddonPathService::GetInstance)
 
 NS_DEFINE_NAMED_CID(NS_TOOLKIT_APPSTARTUP_CID);
 #if defined(MOZ_HAS_PERFSTATS)
 NS_DEFINE_NAMED_CID(NS_TOOLKIT_PERFORMANCESTATSSERVICE_CID);
--- a/toolkit/components/finalizationwitness/FinalizationWitnessService.cpp
+++ b/toolkit/components/finalizationwitness/FinalizationWitnessService.cpp
@@ -13,16 +13,18 @@
 #include "mozilla/Scoped.h"
 #include "mozilla/Services.h"
 #include "nsIObserverService.h"
 #include "nsThreadUtils.h"
 
 
 // Implementation of nsIFinalizationWitnessService
 
+static bool gShuttingDown = false;
+
 namespace mozilla {
 
 namespace {
 
 /**
  * An event meant to be dispatched to the main thread upon finalization
  * of a FinalizationWitness, unless method |forget()| has been called.
  *
@@ -94,18 +96,18 @@ ExtractFinalizationEvent(JSObject *objSe
  * Finalizer for instances of FinalizationWitness.
  *
  * Unless method Forget() has been called, the finalizer displays an error
  * message.
  */
 void Finalize(JSFreeOp *fop, JSObject *objSelf)
 {
   nsRefPtr<FinalizationEvent> event = ExtractFinalizationEvent(objSelf);
-  if (event == nullptr) {
-    // Forget() has been called
+  if (event == nullptr || gShuttingDown) {
+    // NB: event will be null if Forget() has been called
     return;
   }
 
   // Notify observers. Since we are executed during garbage-collection,
   // we need to dispatch the notification to the main thread.
   (void)NS_DispatchToMainThread(event);
   // We may fail at dispatching to the main thread if we arrive too late
   // during shutdown. In that case, there is not much we can do.
@@ -166,17 +168,17 @@ bool Forget(JSContext *cx, unsigned argc
 
 static const JSFunctionSpec sWitnessClassFunctions[] = {
   JS_FN("forget", Forget, 0, JSPROP_READONLY | JSPROP_PERMANENT),
   JS_FS_END
 };
 
 }
 
-NS_IMPL_ISUPPORTS(FinalizationWitnessService, nsIFinalizationWitnessService)
+NS_IMPL_ISUPPORTS(FinalizationWitnessService, nsIFinalizationWitnessService, nsIObserver)
 
 /**
  * Create a new Finalization Witness.
  *
  * A finalization witness is an object whose sole role is to notify
  * observers when it is gc-ed. Once the witness is created, call its
  * method |forget()| to prevent the observers from being notified.
  *
@@ -204,9 +206,35 @@ FinalizationWitnessService::Make(const c
   // Transfer ownership of the addrefed |event| to |objResult|.
   JS_SetReservedSlot(objResult, WITNESS_SLOT_EVENT,
                      JS::PrivateValue(event.forget().take()));
 
   aRetval.setObject(*objResult);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+FinalizationWitnessService::Observe(nsISupports* aSubject,
+                                    const char* aTopic,
+                                    const char16_t* aValue)
+{
+  MOZ_ASSERT(strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0);
+  gShuttingDown = true;
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+  if (obs) {
+    obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
+  }
+
+  return NS_OK;
+}
+
+nsresult
+FinalizationWitnessService::Init()
+{
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+  if (!obs) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
+}
+
 } // namespace mozilla
--- a/toolkit/components/finalizationwitness/FinalizationWitnessService.h
+++ b/toolkit/components/finalizationwitness/FinalizationWitnessService.h
@@ -1,27 +1,32 @@
 /* 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/. */
 
 #ifndef mozilla_finalizationwitnessservice_h__
 #define mozilla_finalizationwitnessservice_h__
 
 #include "nsIFinalizationWitnessService.h"
+#include "nsIObserver.h"
 
 namespace mozilla {
 
 /**
  * XPConnect initializer, for use in the main thread.
  */
-class FinalizationWitnessService final : public nsIFinalizationWitnessService
+class FinalizationWitnessService final : public nsIFinalizationWitnessService,
+                                         public nsIObserver
 {
  public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIFINALIZATIONWITNESSSERVICE
+  NS_DECL_NSIOBSERVER
+
+  nsresult Init();
  private:
   ~FinalizationWitnessService() {}
   void operator=(const FinalizationWitnessService* other) = delete;
 };
 
 } // namespace mozilla
 
 #endif // mozilla_finalizationwitnessservice_h__