[gjs: 1/3] object: Fix GjsCallBackTrampoline's leaks




commit 0ca5c00ded5505cb8a88bb06b1c7673f0f327b41
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Wed Sep 2 18:33:59 2020 +0200

    object: Fix GjsCallBackTrampoline's leaks
    
    Each time we initialize a trampoline for vfunc implementation we never
    unref the memory it allocates, this was not noticed so far as GSlice
    seems to have confused the sanitizer.
    
    To avoid this, let's add a further invalidation notifier where we unref
    the trampoline once the closure has been invalidated.
    
    As per this, when manually invalidating the closure, let's add a
    temporary reference so that we can safely unref it again in the
    invalidation notify function without risks of acting on the last
    reference of the closure itself.

 gi/object.cpp | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
---
diff --git a/gi/object.cpp b/gi/object.cpp
index c8fcad746..1fb8c99e5 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -1450,8 +1450,12 @@ static void invalidate_closure_list(std::forward_list<GClosure*>* closures) {
     // invalidate notifier
     while (!closures->empty()) {
         // This will also free the closure data, through the closure
-        // invalidation mechanism
-        GClosure* closure = *closures->begin();
+        // invalidation mechanism, but adding a temporary reference to
+        // ensure that the closure is still valid when calling invalidation
+        // notify callbacks
+        using GjsAutoGClosure =
+            GjsAutoPointer<GClosure, GClosure, g_closure_unref, g_closure_ref>;
+        GjsAutoGClosure closure(closures->front(), GjsAutoTakeOwnership());
         g_closure_invalidate(closure);
         /* Erase element if not already erased */
         closures->remove(closure);
@@ -2618,6 +2622,11 @@ bool ObjectPrototype::hook_up_vfunc_impl(JSContext* cx,
         g_closure_add_invalidate_notifier(
             trampoline->js_function, this,
             &ObjectPrototype::vfunc_invalidated_notify);
+        g_closure_add_invalidate_notifier(
+            trampoline->js_function, trampoline, [](void* data, GClosure*) {
+                auto* trampoline = static_cast<GjsCallbackTrampoline*>(data);
+                gjs_callback_trampoline_unref(trampoline);
+            });
 
         *((ffi_closure **)method_ptr) = trampoline->closure;
     }


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