Bug 1330018 - Ensure we always unwrap CpowEntries. r=billm,bholley
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
--- 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
@@ -645,26 +645,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,