[gjs/wip/ptomato/785657: 1/2] closure: Don't access objects when destroying context



commit 886961f8edb0768207d9cd6fd7354a4bffd3d455
Author: Philip Chimento <philip endlessm com>
Date:   Tue Aug 22 16:55:00 2017 -0700

    closure: Don't access objects when destroying context
    
    When the JSContext is being destroyed, it's not a good idea to access
    objects, since at this point they are all being destroyed as well. Check
    in the closure invalidation and finalize notifiers that the context is
    not being destroyed before cutting the ties to JS objects.
    
    Also, make sure to call ExposeToActiveJS on the JS object in order to
    prevent it from being dropped out of a garbage collection.

 gi/closure.cpp |   20 ++++++++++++++++----
 1 files changed, 16 insertions(+), 4 deletions(-)
---
diff --git a/gi/closure.cpp b/gi/closure.cpp
index 2528b13..83e8d5a 100644
--- a/gi/closure.cpp
+++ b/gi/closure.cpp
@@ -28,6 +28,7 @@
 #include <util/log.h>
 
 #include "closure.h"
+#include "gjs/context-private.h"
 #include "gjs/jsapi-util-root.h"
 #include "gjs/jsapi-wrapper.h"
 #include "gjs/mem.h"
@@ -166,10 +167,17 @@ closure_set_invalid(gpointer  data,
 {
     Closure *self = &((GjsClosure*) closure)->priv;
 
-    gjs_debug_closure("Invalidating signal closure %p which calls object %p",
-                      closure, self->obj.get());
+    GjsContext *gcx = gjs_context_get_current();
+    if (_gjs_context_destroying(gcx)) {
+        gjs_debug_closure("Invalidating signal closure %p which calls a dead "
+                          "object", closure);
+    } else {
+        gjs_debug_closure("Invalidating signal closure %p which calls object "
+                          "%p", closure, self->obj.get());
+        JS::ExposeObjectToActiveJS(self->obj);
+        self->obj.reset();
+    }
 
-    self->obj.reset();
     self->context = nullptr;
 
     GJS_DEC_COUNTER(closure);
@@ -181,7 +189,11 @@ closure_finalize(gpointer  data,
 {
     Closure *self = &((GjsClosure*) closure)->priv;
 
-    self->~Closure();
+    /* All objects are already destroyed in the last GC when the context is
+     * destroyed. */
+    GjsContext *gcx = gjs_context_get_current();
+    if (!_gjs_context_destroying(gcx))
+        self->~Closure();
 }
 
 void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]