File virtview-git-ff-callbacks.patch of Package virt-viewer
Subject: ff callbacks must be invoked from a clean stack
From: Guido Günther agx@sigxcpu.org Tue Aug 16 08:36:13 2011 -0700
Date: Tue Aug 16 08:36:18 2011 -0700:
Git: f3714e36625168fbd06b63e4b9979e7ea8258712
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.
Index: virt-viewer-0.4.1/src/virt-viewer-events.c
===================================================================
--- virt-viewer-0.4.1.orig/src/virt-viewer-events.c
+++ virt-viewer-0.4.1/src/virt-viewer-events.c
@@ -160,6 +160,23 @@ virt_viewer_events_update_handle(int wat
}
}
+
+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 wat
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 ti
}
}
+
+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 ti
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;
}