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;
 }
 
openSUSE Build Service is sponsored by