[glib] [gsignal] Fix closure invalidation



commit 66b0d95f0ba1939882368b47b01f93289c42ae07
Author: Ryan Lortie <desrt desrt ca>
Date:   Mon Oct 8 18:20:24 2012 -0400

    [gsignal] Fix closure invalidation
    
    If the closure is invalidated we drop the ref on the signal handler
    node, but if the signal is currently being dispatched, the ref could be
    held elsewhere.
    
    Flag that we no longer have an outstanding invalidation handler so that
    we don't try to unregister ourselves when the other ref drops.
    
    Add a testcase that catches this situation.

 gobject/tests/signals.c |   37 +++++++++++++++++++++++++++++++++++++
 1 files changed, 37 insertions(+), 0 deletions(-)
---
diff --git a/gobject/tests/signals.c b/gobject/tests/signals.c
index f9e0da4..019d9e4 100644
--- a/gobject/tests/signals.c
+++ b/gobject/tests/signals.c
@@ -109,6 +109,14 @@ test_class_init (TestClass *klass)
 
   klass->all_types = all_types_handler;
 
+  g_signal_new ("simple",
+                G_TYPE_FROM_CLASS (klass),
+                G_SIGNAL_RUN_LAST,
+                0,
+                NULL, NULL,
+                NULL,
+                G_TYPE_NONE,
+                0);
   g_signal_new ("generic-marshaller-1",
                 G_TYPE_FROM_CLASS (klass),
                 G_SIGNAL_RUN_LAST,
@@ -800,6 +808,34 @@ test_connect (void)
   g_object_unref (test);
 }
 
+static void
+simple_handler1 (GObject *sender,
+                 GObject *target)
+{
+  g_object_unref (target);
+}
+
+static void
+simple_handler2 (GObject *sender,
+                 GObject *target)
+{
+  g_object_unref (target);
+}
+
+static void
+test_destroy_target_object (void)
+{
+  Test *sender, *target1, *target2;
+
+  sender = g_object_new (test_get_type (), NULL);
+  target1 = g_object_new (test_get_type (), NULL);
+  target2 = g_object_new (test_get_type (), NULL);
+  g_signal_connect_object (sender, "simple", G_CALLBACK (simple_handler1), target1, 0);
+  g_signal_connect_object (sender, "simple", G_CALLBACK (simple_handler2), target2, 0);
+  g_signal_emit_by_name (sender, "simple");
+  g_object_unref (sender);
+}
+
 /* --- */
 
 int
@@ -812,6 +848,7 @@ main (int argc,
 
   g_test_add_func ("/gobject/signals/all-types", test_all_types);
   g_test_add_func ("/gobject/signals/variant", test_variant_signal);
+  g_test_add_func ("/gobject/signals/destroy-target-object", test_destroy_target_object);
   g_test_add_func ("/gobject/signals/generic-marshaller-1", test_generic_marshaller_signal_1);
   g_test_add_func ("/gobject/signals/generic-marshaller-2", test_generic_marshaller_signal_2);
   g_test_add_func ("/gobject/signals/generic-marshaller-enum-return-signed", test_generic_marshaller_signal_enum_return_signed);



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