Bug 1290567 - Remove inner-window-destroyed observer in process-content.js at xpcom-shutdown. r?Gijs draft
authorMike Conley <mconley@mozilla.com>
Tue, 16 Aug 2016 09:32:14 -0400
changeset 401161 c777983db07bdcda9c3860d4e1a72cbf881eac5e
parent 397822 e78975b53563d80c99ebfbdf8a9fbf6b829a8a48
child 528414 24bf6a4f9a0a809e3a1edcca287686a86eb360f0
push id26381
push usermconley@mozilla.com
push dateTue, 16 Aug 2016 13:35:18 +0000
reviewersGijs
bugs1290567
milestone51.0a1
Bug 1290567 - Remove inner-window-destroyed observer in process-content.js at xpcom-shutdown. r?Gijs 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();
 }