[Spice-devel] [spice-gtk 3/3] gio-coroutine: Fix leak in corner case
Christophe Fergeau
cfergeau at redhat.com
Mon Feb 23 02:55:48 PST 2015
When delayed emissions of a signal or a notification is queued in an
idle, but the coroutine is re-inited before the idle gets a chance to
run, the idle is now removed after warning about it, but the object
instance which was referenced as part of the signal/notify delayed
emission is never released, causing a leak.
This commit uses g_idle_add_full in order to properly release the object
when the idle is removed.
In order for this to work properly, the coroutine_yieldto call must be
moved from the idle callback to the GDestroyNotify callback. Before that
commit, through coroutine switching magic, we return from the idle
callback long after the g_coroutine_* method which queued it returned.
The GDestroyNotify callback would thus get a pointer to invalid memory
wehn it gets to run (after the idle returns).
---
gtk/gio-coroutine.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/gtk/gio-coroutine.c b/gtk/gio-coroutine.c
index 7527138..dc8e05f 100644
--- a/gtk/gio-coroutine.c
+++ b/gtk/gio-coroutine.c
@@ -202,12 +202,21 @@ static gboolean emit_main_context(gpointer opaque)
signal->detail, signal->var_args);
signal->notified = TRUE;
- coroutine_yieldto(signal->caller, NULL);
return FALSE;
}
static void
+unref_instance(gpointer opaque)
+{
+ struct signal_data *data = opaque;
+
+ g_object_unref(data->instance);
+ if (data->notified)
+ coroutine_yieldto(data->caller, NULL);
+}
+
+static void
run_in_idle(GSourceFunc idle_callback, gpointer opaque)
{
struct signal_data *data = opaque;
@@ -215,7 +224,9 @@ run_in_idle(GSourceFunc idle_callback, gpointer opaque)
g_warn_if_fail(data->caller->idle_id == 0);
g_object_ref(data->instance);
- data->caller->idle_id = g_idle_add(idle_callback, data);
+ data->caller->idle_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
+ idle_callback, data,
+ unref_instance);
/* This switches to the system coroutine context, lets
* the idle function run to dispatch the signal, and
* finally returns once complete. ie this is synchronous
@@ -228,7 +239,6 @@ run_in_idle(GSourceFunc idle_callback, gpointer opaque)
g_source_remove(data->caller->idle_id);
}
data->caller->idle_id = 0;
- g_object_unref(data->instance);
}
void
@@ -262,7 +272,6 @@ static gboolean notify_main_context(gpointer opaque)
g_object_notify(signal->instance, signal->propname);
signal->notified = TRUE;
- coroutine_yieldto(signal->caller, NULL);
return FALSE;
}
--
2.1.0
More information about the Spice-devel
mailing list