From f3714e36625168fbd06b63e4b9979e7ea8258712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Tue, 16 Aug 2011 08:36:13 -0700 Subject: [PATCH] ff callbacks must be invoked from a clean stack If 'ff' callbacks are invoked directly from the remove callback they will likely deadlock in libvirt. They must be invoked from a clean stack, so switch to using a glib idle callback. --- src/virt-viewer-events.c | 47 +++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/src/virt-viewer-events.c b/src/virt-viewer-events.c index 108f97d..87df739 100644 --- a/src/virt-viewer-events.c +++ b/src/virt-viewer-events.c @@ -160,6 +160,23 @@ virt_viewer_events_update_handle(int watch, } } + +static gboolean +virt_viewer_events_cleanup_handle(gpointer user_data) +{ + struct virt_viewer_events_handle *data = user_data; + + DEBUG_LOG("Cleanup of handle %p", data); + g_return_val_if_fail(data != NULL, FALSE); + + if (data->ff) + (data->ff)(data->opaque); + + free(data); + return FALSE; +} + + static int virt_viewer_events_remove_handle(int watch) { @@ -172,13 +189,14 @@ virt_viewer_events_remove_handle(int watch) DEBUG_LOG("Remove handle %d %d", watch, data->fd); + if (!data->source) + return -1; + g_source_remove(data->source); data->source = 0; data->events = 0; - if (data->ff) - (data->ff)(data->opaque); - free(data); + g_idle_add(virt_viewer_events_cleanup_handle, data); return 0; } @@ -279,6 +297,23 @@ virt_viewer_events_update_timeout(int timer, } } + +static gboolean +virt_viewer_events_cleanup_timeout(gpointer user_data) +{ + struct virt_viewer_events_timeout *data = user_data; + + DEBUG_LOG("Cleanup of timeout %p", data); + g_return_val_if_fail(data != NULL, FALSE); + + if (data->ff) + (data->ff)(data->opaque); + + free(data); + return FALSE; +} + + static int virt_viewer_events_remove_timeout(int timer) { @@ -297,11 +332,7 @@ virt_viewer_events_remove_timeout(int timer) g_source_remove(data->source); data->source = 0; - if (data->ff) - (data->ff)(data->opaque); - - free(data); - + g_idle_add(virt_viewer_events_cleanup_timeout, data); return 0; }