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 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel