[Spice-devel] [spice-gtk v1] spicevmc: don't disconnect on "cancel"

Victor Toso victortoso at redhat.com
Mon May 2 13:16:05 UTC 2016


spicevmc was designed so its _finish functions should always be called;
With the gtask integration both _finish functions are trying to
disconnect the GCancellabe even in the 'cancel' context which leads to
a deadlock as explained in the documentation.

Resolves: https://bugs.freedesktop.org/show_bug.cgi?id=95032
---
 src/vmcstream.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/src/vmcstream.c b/src/vmcstream.c
index 5dd2799..a8bedf5 100644
--- a/src/vmcstream.c
+++ b/src/vmcstream.c
@@ -183,13 +183,10 @@ read_cancelled(GCancellable *cancellable,
                             G_IO_ERROR, G_IO_ERROR_CANCELLED,
                             "read cancelled");
 
+    /* With GTask, we don't need to deal with GCancellable when task is
+     * cancelled within cancellable callback as it could lead to deadlocks
+     * e.g: https://bugzilla.gnome.org/show_bug.cgi?id=705395 */
     g_clear_object(&self->task);
-
-    /* See FIXME */
-    /* if (self->cancellable) { */
-    /*     g_cancellable_disconnect(self->cancellable, self->cancel_id); */
-    /*     g_clear_object(&self->cancellable); */
-    /* } */
 }
 
 G_GNUC_INTERNAL void
@@ -230,13 +227,14 @@ spice_vmc_input_stream_read_all_finish(GInputStream *stream,
 {
     GTask *task = G_TASK(result);
     SpiceVmcInputStream *self = SPICE_VMC_INPUT_STREAM(stream);
+    GCancellable *cancel;
 
     g_return_val_if_fail(g_task_is_valid(task, self), -1);
-
-    /* FIXME: calling _finish() is required. Disconnecting in
-       read_cancelled() causes a deadlock. #705395 */
-    g_cancellable_disconnect(g_task_get_cancellable(task), self->cancel_id);
-
+    cancel = g_task_get_cancellable(task);
+    if (!g_cancellable_is_cancelled(cancel)) {
+         g_cancellable_disconnect(cancel, self->cancel_id);
+         self->cancel_id = 0;
+    }
     return g_task_propagate_int(task, error);
 }
 
@@ -276,13 +274,15 @@ spice_vmc_input_stream_read_finish(GInputStream *stream,
 {
     GTask *task = G_TASK(result);
     SpiceVmcInputStream *self = SPICE_VMC_INPUT_STREAM(stream);
+    GCancellable *cancel;
 
     g_return_val_if_fail(g_task_is_valid(task, self), -1);
 
-    /* FIXME: calling _finish() is required. Disconnecting in
-       read_cancelled() causes a deadlock. #705395 */
-    g_cancellable_disconnect(g_task_get_cancellable(task), self->cancel_id);
-
+    cancel = g_task_get_cancellable(task);
+    if (!g_cancellable_is_cancelled(cancel)) {
+         g_cancellable_disconnect(cancel, self->cancel_id);
+         self->cancel_id = 0;
+    }
     return g_task_propagate_int(task, error);
 }
 
-- 
2.5.5



More information about the Spice-devel mailing list