[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