Bug 1330018 - Ensure we always unwrap CpowEntries. r=bholley, r=billm, a=jcristau
authorAndrew McCreight <continuation@gmail.com>
Fri, 13 Jan 2017 13:50:35 -0800
changeset 353688 5a6e8c89b306ba8f959822c38f0b0ca3664e8b53
parent 353687 338a1630d1db0573f0ac96be426f5b6f5198d474
child 353689 cd4fc47221cb3c5333f0b23fcb1dac38c8c2b35d
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley, billm, jcristau
bugs1330018
milestone52.0a2
Bug 1330018 - Ensure we always unwrap CpowEntries. r=bholley, r=billm, a=jcristau We can drop async messages that contain CPOWs, which can cause us to leak them either until we successfully send a CPOW or forever, depending on the direction of the message. This is causing intermittent leaks until shutdown with e10s-multi. MozReview-Commit-ID: 3iIaIBZKZR2
js/ipc/CrossProcessObjectWrappers.h
js/ipc/JavaScriptShared.cpp
--- a/js/ipc/CrossProcessObjectWrappers.h
+++ b/js/ipc/CrossProcessObjectWrappers.h
@@ -44,21 +44,24 @@ class CPOWManager
 };
 
 class CrossProcessCpowHolder : public CpowHolder
 {
   public:
     CrossProcessCpowHolder(dom::CPOWManagerGetter* managerGetter,
                            const InfallibleTArray<CpowEntry>& cpows);
 
+    ~CrossProcessCpowHolder();
+
     bool ToObject(JSContext* cx, JS::MutableHandleObject objp);
 
   private:
     CPOWManager* js_;
     const InfallibleTArray<CpowEntry>& cpows_;
+    bool unwrapped_;
 };
 
 CPOWManager*
 CPOWManagerFor(PJavaScriptParent* aParent);
 
 CPOWManager*
 CPOWManagerFor(PJavaScriptChild* aChild);
 
--- a/js/ipc/JavaScriptShared.cpp
+++ b/js/ipc/JavaScriptShared.cpp
@@ -636,26 +636,48 @@ JavaScriptShared::fromObjectOrNullVarian
         return nullptr;
 
     return fromObjectVariant(cx, objVar.get_ObjectVariant());
 }
 
 CrossProcessCpowHolder::CrossProcessCpowHolder(dom::CPOWManagerGetter* managerGetter,
                                                const InfallibleTArray<CpowEntry>& cpows)
   : js_(nullptr),
-    cpows_(cpows)
+    cpows_(cpows),
+    unwrapped_(false)
 {
     // Only instantiate the CPOW manager if we might need it later.
     if (cpows.Length())
         js_ = managerGetter->GetCPOWManager();
 }
 
+CrossProcessCpowHolder::~CrossProcessCpowHolder()
+{
+    if (cpows_.Length() && !unwrapped_) {
+        // This should only happen if a message manager message
+        // containing CPOWs gets ignored for some reason. We need to
+        // unwrap every incoming CPOW in this process to ensure that
+        // the corresponding part of the CPOW in the other process
+        // will eventually be collected. The scope for this object
+        // doesn't really matter, because it immediately becomes
+        // garbage.
+        AutoJSAPI jsapi;
+        if (!jsapi.Init(xpc::PrivilegedJunkScope()))
+            return;
+        JSContext* cx = jsapi.cx();
+        JS::Rooted<JSObject*> cpows(cx);
+        js_->Unwrap(cx, cpows_, &cpows);
+    }
+}
+
 bool
 CrossProcessCpowHolder::ToObject(JSContext* cx, JS::MutableHandleObject objp)
 {
+    unwrapped_ = true;
+
     if (!cpows_.Length())
         return true;
 
     return js_->Unwrap(cx, cpows_, objp);
 }
 
 bool
 JavaScriptShared::Unwrap(JSContext* cx, const InfallibleTArray<CpowEntry>& aCpows,