Bug 1290567 - Remove inner-window-destroyed observer in process-content.js at xpcom-shutdown. r=Gijs, a=ritu
authorMike Conley <mconley@mozilla.com>
Tue, 16 Aug 2016 09:32:14 -0400
changeset 350548 87d82a4489f978b529f076ec2c26652cfbf9915e
parent 350547 69df4d73eeee9b696581a0936ce71e939812641d
child 350549 2c9b14f4694542e164671187d1d9da7aa01ef118
push id1230
push userjlund@mozilla.com
push dateMon, 31 Oct 2016 18:13:35 +0000
treeherdermozilla-release@5e06e3766db2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs, ritu
bugs1290567
milestone50.0
Bug 1290567 - Remove inner-window-destroyed observer in process-content.js at xpcom-shutdown. r=Gijs, a=ritu It seems to be possible for an inner-window-destroyed notification to be dispatched after xpcom-shutdown. This means that communications over the Services.cpmm are attempted after the connection to the parent process has already been torn down. This can cause an Exception to be thrown, which can keep the ContentProcessMessageManager alive long enough to cause SpiderMonkey to complain that there are still living elements in its heap at JS shutdown time. MozReview-Commit-ID: wmCHtqcjkJ
toolkit/content/process-content.js
--- a/toolkit/content/process-content.js
+++ b/toolkit/content/process-content.js
@@ -16,17 +16,49 @@ const gInContentProcess = Services.appin
 
 Services.cpmm.addMessageListener("gmp-plugin-crash", msg => {
   let gmpservice = Cc["@mozilla.org/gecko-media-plugin-service;1"]
                      .getService(Ci.mozIGeckoMediaPluginService);
 
   gmpservice.RunPluginCrashCallbacks(msg.data.pluginID, msg.data.pluginName);
 });
 
-// Forward inner-window-destroyed notifications with the inner window ID,
-// so that code in the parent that should do something when content
-// windows go away can do it
 if (gInContentProcess) {
-  Services.obs.addObserver((subject, topic, data) => {
-    let innerWindowID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
-    Services.cpmm.sendAsyncMessage("Toolkit:inner-window-destroyed", innerWindowID);
-  }, "inner-window-destroyed", false);
+  let ProcessObserver = {
+    TOPICS: [
+      "inner-window-destroyed",
+      "xpcom-shutdown",
+    ],
+
+    init() {
+      for (let topic of this.TOPICS) {
+        Services.obs.addObserver(this, topic, false);
+      }
+    },
+
+    uninit() {
+      for (let topic of this.TOPICS) {
+        Services.obs.removeObserver(this, topic);
+      }
+    },
+
+    observe(subject, topic, data) {
+      switch (topic) {
+        case "inner-window-destroyed": {
+          // Forward inner-window-destroyed notifications with the
+          // inner window ID, so that code in the parent that should
+          // do something when content windows go away can do it
+          let innerWindowID =
+            subject.QueryInterface(Ci.nsISupportsPRUint64).data;
+          Services.cpmm.sendAsyncMessage("Toolkit:inner-window-destroyed",
+                                         innerWindowID);
+          break;
+        }
+        case "xpcom-shutdown": {
+          this.uninit();
+          break;
+        }
+      }
+    },
+  };
+
+  ProcessObserver.init();
 }