summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGuido Günther <agx@sigxcpu.org>2011-08-16 08:36:13 -0700
committerDaniel P. Berrange <berrange@redhat.com>2011-08-16 08:36:18 -0700
commitf3714e36625168fbd06b63e4b9979e7ea8258712 (patch)
treef31b20d7cf3ae56839f50552fb179778faec9b76 /src
parente155f7f656dd2bb5f939996be583e908afeec2a8 (diff)
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.
Diffstat (limited to 'src')
-rw-r--r--src/virt-viewer-events.c47
1 files 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;
}