[glib] gmain: Unref GSourceCallbackFuncs _before_ finalising GSource



commit 90dd9ff363729b2f797356515967c3b2a5f93b47
Author: Philip Withnall <philip withnall collabora co uk>
Date:   Thu Sep 25 10:18:39 2014 +0100

    gmain: Unref GSourceCallbackFuncs _before_ finalising GSource
    
    Rather than unreffing them _after_ finalising the GSource and freeing
    its struct. This fixes the case where the GSourceCallbackFuncs data
    contains a pointer to the GSource, and the unref() function operates on
    that pointer, e.g. by calling g_source_destroy(). This happens when
    using g_source_set_dummy_callback() on a GSource, as the generated
    GClosure needs to destroy the GSource when it is invalidated, which
    could happen (at latest) when the GSourceCallbackFuncs.unref() function
    is called during finalisation of the GSource.
    
    By moving the GSourceCallbackFuncs.unref() invocation higher up in
    g_source_unref_internal(), it becomes re-entrancy-safe for GSource
    methods.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=692034

 glib/gmain.c |   28 ++++++++++++++++------------
 1 files changed, 16 insertions(+), 12 deletions(-)
---
diff --git a/glib/gmain.c b/glib/gmain.c
index 6a8a275..0f67c17 100644
--- a/glib/gmain.c
+++ b/glib/gmain.c
@@ -2122,6 +2122,21 @@ g_source_unref_internal (GSource      *source,
           source->ref_count--;
        }
 
+      if (old_cb_funcs)
+        {
+          /* Temporarily increase the ref count again so that GSource methods
+           * can be called from callback_funcs.unref(). */
+          source->ref_count++;
+          if (context)
+            UNLOCK_CONTEXT (context);
+
+          old_cb_funcs->unref (old_cb_data);
+
+          if (context)
+            LOCK_CONTEXT (context);
+          source->ref_count--;
+        }
+
       g_free (source->name);
       source->name = NULL;
 
@@ -2146,20 +2161,9 @@ g_source_unref_internal (GSource      *source,
 
       g_free (source);
     }
-  
+
   if (!have_lock && context)
     UNLOCK_CONTEXT (context);
-
-  if (old_cb_funcs)
-    {
-      if (have_lock)
-       UNLOCK_CONTEXT (context);
-      
-      old_cb_funcs->unref (old_cb_data);
-
-      if (have_lock)
-       LOCK_CONTEXT (context);
-    }
 }
 
 /**


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