Bug 1119753 - Fix CPOW GC crash (r=jonco)
authorBill McCloskey <wmccloskey@mozilla.com>
Fri, 16 Jan 2015 09:56:30 -0800
changeset 224234 8c6cbca7251a822c51441f837dd085071bb010e8
parent 224233 4aefc5bf7ec4d876ea5b0bc06c8ffbd79d8d081e
child 224235 68b90a5407b2357565d2804028e6abd135ae4a15
push id54164
push userwmccloskey@mozilla.com
push dateFri, 16 Jan 2015 17:58:13 +0000
treeherdermozilla-inbound@68b90a5407b2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco
bugs1119753
milestone38.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 1119753 - Fix CPOW GC crash (r=jonco)
js/ipc/JavaScriptParent.cpp
js/ipc/JavaScriptShared.cpp
js/ipc/JavaScriptShared.h
js/ipc/WrapperOwner.cpp
--- a/js/ipc/JavaScriptParent.cpp
+++ b/js/ipc/JavaScriptParent.cpp
@@ -46,21 +46,19 @@ JavaScriptParent::init()
 
     JS_AddExtraGCRootsTracer(rt_, TraceParent, this);
     return true;
 }
 
 void
 JavaScriptParent::trace(JSTracer *trc)
 {
-    if (active()) {
-        objects_.trace(trc);
-        unwaivedObjectIds_.trace(trc);
-        waivedObjectIds_.trace(trc);
-    }
+    objects_.trace(trc);
+    unwaivedObjectIds_.trace(trc);
+    waivedObjectIds_.trace(trc);
 }
 
 JSObject *
 JavaScriptParent::scopeForTargetObjects()
 {
     // CPWOWs from the child need to point into the parent's unprivileged junk
     // scope so that a compromised child cannot compromise the parent. In
     // practice, this means that a child process can only (a) hold parent
--- a/js/ipc/JavaScriptShared.cpp
+++ b/js/ipc/JavaScriptShared.cpp
@@ -68,16 +68,28 @@ IdToObjectMap::add(ObjectId id, JSObject
 }
 
 void
 IdToObjectMap::remove(ObjectId id)
 {
     table_.remove(id);
 }
 
+void
+IdToObjectMap::clear()
+{
+    table_.clear();
+}
+
+bool
+IdToObjectMap::empty() const
+{
+    return table_.empty();
+}
+
 ObjectToIdMap::ObjectToIdMap()
   : table_(nullptr)
 {
 }
 
 ObjectToIdMap::~ObjectToIdMap()
 {
     if (table_) {
@@ -152,16 +164,22 @@ ObjectToIdMap::keyMarkCallback(JSTracer 
 }
 
 void
 ObjectToIdMap::remove(JSObject *obj)
 {
     table_->remove(obj);
 }
 
+void
+ObjectToIdMap::clear()
+{
+    table_->clear();
+}
+
 bool JavaScriptShared::sLoggingInitialized;
 bool JavaScriptShared::sLoggingEnabled;
 bool JavaScriptShared::sStackLoggingEnabled;
 
 JavaScriptShared::JavaScriptShared(JSRuntime *rt)
   : rt_(rt),
     refcount_(1),
     nextSerialNumber_(1)
@@ -176,16 +194,21 @@ JavaScriptShared::JavaScriptShared(JSRun
             Preferences::AddBoolVarCache(&sLoggingEnabled,
                                          "dom.ipc.cpows.log.enabled", false);
             Preferences::AddBoolVarCache(&sStackLoggingEnabled,
                                          "dom.ipc.cpows.log.stack", false);
         }
     }
 }
 
+JavaScriptShared::~JavaScriptShared()
+{
+    MOZ_RELEASE_ASSERT(cpows_.empty());
+}
+
 bool
 JavaScriptShared::init()
 {
     if (!objects_.init())
         return false;
     if (!cpows_.init())
         return false;
     if (!unwaivedObjectIds_.init())
--- a/js/ipc/JavaScriptShared.h
+++ b/js/ipc/JavaScriptShared.h
@@ -105,16 +105,19 @@ class IdToObjectMap
     bool init();
     void trace(JSTracer *trc);
     void sweep();
 
     bool add(ObjectId id, JSObject *obj);
     JSObject *find(ObjectId id);
     void remove(ObjectId id);
 
+    void clear();
+    bool empty() const;
+
   private:
     Table table_;
 };
 
 // Map JSObjects -> ids
 class ObjectToIdMap
 {
     typedef js::PointerHasher<JSObject *, 3> Hasher;
@@ -126,30 +129,31 @@ class ObjectToIdMap
 
     bool init();
     void trace(JSTracer *trc);
     void sweep();
 
     bool add(JSContext *cx, JSObject *obj, ObjectId id);
     ObjectId find(JSObject *obj);
     void remove(JSObject *obj);
+    void clear();
 
   private:
     static void keyMarkCallback(JSTracer *trc, JSObject *key, void *data);
 
     Table *table_;
 };
 
 class Logging;
 
 class JavaScriptShared
 {
   public:
     explicit JavaScriptShared(JSRuntime *rt);
-    virtual ~JavaScriptShared() {}
+    virtual ~JavaScriptShared();
 
     bool init();
 
     void decref();
     void incref();
 
     bool Unwrap(JSContext *cx, const InfallibleTArray<CpowEntry> &aCpows, JS::MutableHandleObject objp);
     bool Wrap(JSContext *cx, JS::HandleObject aObj, InfallibleTArray<CpowEntry> *outCpows);
--- a/js/ipc/WrapperOwner.cpp
+++ b/js/ipc/WrapperOwner.cpp
@@ -872,16 +872,20 @@ WrapperOwner::domInstanceOf(JSContext *c
 
     return ok(cx, status);
 }
 
 void
 WrapperOwner::ActorDestroy(ActorDestroyReason why)
 {
     inactive_ = true;
+
+    objects_.clear();
+    unwaivedObjectIds_.clear();
+    waivedObjectIds_.clear();
 }
 
 bool
 WrapperOwner::ipcfail(JSContext *cx)
 {
     JS_ReportError(cx, "child process crashed or timedout");
     return false;
 }