[glib] signals: Ensure we ref handler in emission fast path



commit aede77464259e6d50e724113c16f301367201a72
Author: Alexander Larsson <alexl redhat com>
Date:   Thu Feb 21 16:10:36 2013 +0100

    signals: Ensure we ref handler in emission fast path
    
    We need to keep a reference to the handler in the fast path, just like
    in the slow path, otherwise if another thread disconnects the handler
    we may destroy the closure while we're using it without the lock held.
    
    We also move the freeing of the instance to after the emission is totally
    done as the handler_unref_R (and the tracepoint) reference it.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=694253

 gobject/gsignal.c |   12 +++++++++++-
 1 files changed, 11 insertions(+), 1 deletions(-)
---
diff --git a/gobject/gsignal.c b/gobject/gsignal.c
index 061f16f..e2a8439 100644
--- a/gobject/gsignal.c
+++ b/gobject/gsignal.c
@@ -3127,6 +3127,7 @@ g_signal_emit_valist (gpointer instance,
       )
     {
       HandlerList* hlist = handler_list_lookup (node->signal_id, instance);
+      Handler *fastpath_handler = NULL;
       Handler *l;
       GClosure *closure = NULL;
       gboolean fastpath = TRUE;
@@ -3159,6 +3160,7 @@ g_signal_emit_valist (gpointer instance,
                }
              else
                {
+                  fastpath_handler = l;
                  closure = l->closure;
                  if (l->after)
                    run_type = G_SIGNAL_RUN_LAST;
@@ -3207,6 +3209,9 @@ g_signal_emit_valist (gpointer instance,
          emission.chain_type = instance_type;
          emission_push (&g_recursive_emissions, &emission);
 
+          if (fastpath_handler)
+            handler_ref (fastpath_handler);
+
          SIGNAL_UNLOCK ();
 
          TRACE(GOBJECT_SIGNAL_EMIT(signal_id, detail, instance, instance_type));
@@ -3227,7 +3232,6 @@ g_signal_emit_valist (gpointer instance,
                                    node->n_params,
                                    node->param_types);
              accumulate (&emission.ihint, &emission_return, &accu, accumulator);
-             g_object_unref (instance);
            }
 
          SIGNAL_LOCK ();
@@ -3235,6 +3239,9 @@ g_signal_emit_valist (gpointer instance,
          emission.chain_type = G_TYPE_NONE;
          emission_pop (&g_recursive_emissions, &emission);
 
+          if (fastpath_handler)
+            handler_unref_R (signal_id, instance, fastpath_handler);
+
          SIGNAL_UNLOCK ();
 
          if (accumulator)
@@ -3267,6 +3274,9 @@ g_signal_emit_valist (gpointer instance,
          
          TRACE(GOBJECT_SIGNAL_EMIT_END(signal_id, detail, instance, instance_type));
 
+          if (closure != NULL)
+            g_object_unref (instance);
+
          return;
        }
     }


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