[glib] signals: Ensure we ref handler in emission fast path
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] signals: Ensure we ref handler in emission fast path
- Date: Thu, 21 Feb 2013 15:49:06 +0000 (UTC)
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]