[Spice-devel] [PATCH spice-gtk 14/15] channel-main: Cancel active file-xfers on channel/agent disconnect

Hans de Goede hdegoede at redhat.com
Sat Mar 9 03:06:34 PST 2013


Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 gtk/channel-main.c | 44 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 40 insertions(+), 4 deletions(-)

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 1ae300c..ad6c0c6 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -69,6 +69,7 @@ typedef struct SpiceFileXferTask {
     uint64_t                       read_bytes;
     uint64_t                       file_size;
     GError                         *error;
+    GError                         *cancelled;
 } SpiceFileXferTask;
 
 struct _SpiceMainChannelPrivate  {
@@ -332,6 +333,8 @@ static void spice_channel_iterate_write(SpiceChannel *channel)
 static void spice_main_channel_reset_agent(SpiceMainChannel *channel)
 {
     SpiceMainChannelPrivate *c = channel->priv;
+    GError *error;
+    GList *l;
 
     c->agent_connected = FALSE;
     c->agent_caps_received = FALSE;
@@ -340,6 +343,21 @@ static void spice_main_channel_reset_agent(SpiceMainChannel *channel)
     g_free(c->agent_msg_data);
     c->agent_msg_data = NULL;
     c->agent_msg_size = 0;
+
+    for (l = c->file_xfer_task_list; l != NULL; l = l->next) {
+        SpiceFileXferTask *task = (SpiceFileXferTask *)l->data;
+
+        if (task->closed || task->cancelled)
+            continue;
+
+        error = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+                            "Agent connection closed");
+        if (task->file_stream == NULL ||
+                g_input_stream_has_pending(G_INPUT_STREAM(task->file_stream)))
+            task->cancelled = error;
+        else
+            file_xfer_completed(task, error);
+    }
 }
 
 /* main or coroutine context */
@@ -1627,6 +1645,14 @@ static void file_xfer_read_cb(GObject *source_object,
 
     count = g_input_stream_read_finish(G_INPUT_STREAM(task->file_stream),
                                        res, &error);
+
+    if (task->cancelled) {
+        g_clear_error(&error);
+        file_xfer_completed(task, task->cancelled);
+        task->cancelled = NULL;
+        return;
+    }
+
     if (count > 0) {
         task->read_bytes += count;
         file_xfer_queue(task, count);
@@ -2602,9 +2628,13 @@ static void file_xfer_info_async_cb(GObject *obj, GAsyncResult *res, gpointer da
     gsize /*msg_size*/ data_len;
     gchar *string;
     SpiceFileXferTask *task = (SpiceFileXferTask *)data;
-    SpiceMainChannelPrivate *c = task->channel->priv;
 
     info = g_file_query_info_finish(file, res, &error);
+    if (task->cancelled) {
+        g_clear_error(&error);
+        error = task->cancelled;
+        task->cancelled = NULL;
+    }
     if (error)
         goto failed;
 
@@ -2627,9 +2657,6 @@ static void file_xfer_info_async_cb(GObject *obj, GAsyncResult *res, gpointer da
         goto failed;
 
     /* Create file-xfer start message */
-    CHANNEL_DEBUG(task->channel, "Insert a xfer task:%d to task list", task->id);
-    c->file_xfer_task_list = g_list_append(c->file_xfer_task_list, task);
-
     msg.id = task->id;
     agent_msg_queue_many(task->channel, VD_AGENT_FILE_XFER_START,
                          &msg, sizeof(msg),
@@ -2649,6 +2676,11 @@ static void file_xfer_read_async_cb(GObject *obj, GAsyncResult *res, gpointer da
     GError *error = NULL;
 
     task->file_stream = g_file_read_finish(file, res, &error);
+    if (task->cancelled) {
+        g_clear_error(&error);
+        error = task->cancelled;
+        task->cancelled = NULL;
+    }
     if (error) {
         task->error = error;
         file_xfer_close_cb(NULL, NULL, task);
@@ -2673,6 +2705,7 @@ static void file_xfer_send_start_msg_async(SpiceMainChannel *channel,
                                            GAsyncReadyCallback callback,
                                            gpointer user_data)
 {
+    SpiceMainChannelPrivate *c = channel->priv;
     SpiceFileXferTask *task;
     static uint32_t xfer_id;    /* Used to identify task id */
 
@@ -2687,6 +2720,9 @@ static void file_xfer_send_start_msg_async(SpiceMainChannel *channel,
     task->callback = callback;
     task->user_data = user_data;
 
+    CHANNEL_DEBUG(task->channel, "Insert a xfer task:%d to task list", task->id);
+    c->file_xfer_task_list = g_list_append(c->file_xfer_task_list, task);
+
     g_file_read_async(file,
                       G_PRIORITY_DEFAULT,
                       cancellable,
-- 
1.8.1.4



More information about the Spice-devel mailing list