[Spice-commits] 16 commits - gtk/channel-main.c gtk/spice-widget.c

Hans de Goede jwrdegoede at kemper.freedesktop.org
Tue Apr 9 04:10:39 PDT 2013


 gtk/channel-main.c |  195 +++++++++++++++++++++++++++++------------------------
 gtk/spice-widget.c |    2 
 2 files changed, 111 insertions(+), 86 deletions(-)

New commits:
commit 0c0c94b7d7898feb4bb33caf383242ef26b62d09
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Tue Mar 26 12:34:01 2013 +0100

    channel-main: Don't g_warn when not finding a file-xfer-id
    
    Since the agent channel can have a significant latency, it is possible
    for a cancel send from the client to the agent and a status message from
    the agent to cross each other. If this happens then the file-xfer will no
    longer be on the list.
    
    Printing a g_warning on this (rare but triggerable) condition will only get
    us hard to debug bug reports, so turn it into a SPICE_DEBUG.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 01c0659..11cd0f9 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -1704,8 +1704,10 @@ static void file_xfer_handle_status(SpiceMainChannel *channel,
 
     l = g_list_find_custom(c->file_xfer_task_list, &msg->id,
                            file_xfer_task_find);
-
-    g_return_if_fail(l != NULL);
+    if (l == NULL) {
+        SPICE_DEBUG("cannot find task %d", msg->id);
+        return;
+    }
     task = l->data;
 
     SPICE_DEBUG("task %d received response %d", msg->id, msg->result);
commit 0b81c90deaa51c6233b911e35a6adff29c3643f9
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 8 15:41:54 2013 +0100

    channel-main: Cancel active file-xfers on channel/agent disconnect
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 7513ead..01c0659 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -165,6 +165,7 @@ static gboolean main_migrate_handshake_done(gpointer data);
 static void spice_main_channel_send_migration_handshake(SpiceChannel *channel);
 static void file_xfer_continue_read(SpiceFileXferTask *task);
 static void file_xfer_completed(SpiceFileXferTask *task, GError *error);
+static void file_xfer_flushed(SpiceMainChannel *channel, gboolean success);
 
 /* ------------------------------------------------------------------ */
 
@@ -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,15 @@ 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;
+
+        error = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+                            "Agent connection closed");
+        file_xfer_completed(task, error);
+    }
+    file_xfer_flushed(channel, FALSE);
 }
 
 /* main or coroutine context */
commit e86fe5e8c8e7921062f881b78e439f21d4304b8d
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Mar 21 17:29:41 2013 +0100

    channel-main: Check no callbacks are pending on xfer start and end
    
    We should never have pending callbacks when we receive a file-xfer start or
    end (success) message from the agent.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 5a05651..7513ead 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -1700,6 +1700,11 @@ static void file_xfer_handle_status(SpiceMainChannel *channel,
 
     switch (msg->result) {
     case VD_AGENT_FILE_XFER_STATUS_CAN_SEND_DATA:
+        if (task->pending) {
+            error = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+                           "transfer received CAN_SEND_DATA in pending state");
+            break;
+        }
         file_xfer_continue_read(task);
         return;
     case VD_AGENT_FILE_XFER_STATUS_CANCELLED:
@@ -1711,6 +1716,9 @@ static void file_xfer_handle_status(SpiceMainChannel *channel,
                             "some errors occurred in the spice agent");
         break;
     case VD_AGENT_FILE_XFER_STATUS_SUCCESS:
+        if (task->pending)
+            error = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+                                "transfer received success in pending state");
         break;
     default:
         g_warn_if_reached();
commit df9f513145217e8aabfd534010e6eec036896abe
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Mar 21 17:15:41 2013 +0100

    channel-main: Don't call g_input_stream_close on a NULL stream
    
    If we fail to open a file, task->file_stream will be NULL, so we should
    not call g_input_stream_close on it.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index c7ac12d..5a05651 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -2591,6 +2591,11 @@ static void file_xfer_completed(SpiceFileXferTask *task, GError *error)
     if (task->pending)
         return;
 
+    if (!task->file_stream) {
+        file_xfer_close_cb(NULL, NULL, task);
+        return;
+    }
+
     g_input_stream_close_async(G_INPUT_STREAM(task->file_stream),
                                G_PRIORITY_DEFAULT,
                                task->cancellable,
commit dc164370b6d68be289f0f41b2a29f7f7c6c345d1
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Mar 7 13:54:16 2013 +0100

    channel-main: Allow calling file_xfer_close_cb with a NULL object
    
    So that it can used for cleanup before we've a file_stream.
    
    Note this also gets rid of the weird double initialization of the local
    stream variable.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 3222591..c7ac12d 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -1562,17 +1562,18 @@ static void file_xfer_close_cb(GObject      *object,
 {
     GSimpleAsyncResult *res;
     SpiceFileXferTask *task;
-    GInputStream *stream = G_INPUT_STREAM(object);
     GError *error = NULL;
 
-    stream = G_INPUT_STREAM(object);
     task = user_data;
 
-    g_input_stream_close_finish(stream, close_res, &error);
-    if (error) {
-        /* This error dont need to report to user, just print a log */
-        SPICE_DEBUG("close file error: %s", error->message);
-        g_clear_error(&error);
+    if (object) {
+        GInputStream *stream = G_INPUT_STREAM(object);
+        g_input_stream_close_finish(stream, close_res, &error);
+        if (error) {
+            /* This error dont need to report to user, just print a log */
+            SPICE_DEBUG("close file error: %s", error->message);
+            g_clear_error(&error);
+        }
     }
 
     /* Notify to user that files have been transferred or something error
commit d0b3699903bbc186339e7681c7088e5b624112c4
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Mar 21 16:58:16 2013 +0100

    channel-main: Don't close the file_stream if callbacks are pending
    
    If file_xfer_completed gets called while callbacks are pending we should
    not call g_input_stream_close_async, because:
    1) Doing so while another operation is pending on the file_stream will fail
    2) Doing so while a non file_stream callback is pending may result in the
    task being freed before the callback runs, resulting in a use after free.
    
    This patch fixes this by setting a pending flag when any callbacks are
    scheduled, and clearing it when it runs + checking for task->error
    from all callbacks and if that is set call file_xfer_completed again.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index b0d60eb..3222591 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -55,6 +55,7 @@ typedef struct spice_migrate spice_migrate;
 #define FILE_XFER_CHUNK_SIZE (VD_AGENT_MAX_DATA_SIZE * 32)
 typedef struct SpiceFileXferTask {
     uint32_t                       id;
+    gboolean                       pending;
     GFile                          *file;
     SpiceMainChannel               *channel;
     GFileInputStream               *file_stream;
@@ -1600,9 +1601,9 @@ static void file_xfer_data_flushed_cb(GObject *source_object,
     SpiceMainChannel *channel = (SpiceMainChannel *)source_object;
     GError *error = NULL;
 
+    task->pending = FALSE;
     file_xfer_flush_finish(channel, res, &error);
-
-    if (error != NULL) {
+    if (error || task->error) {
         file_xfer_completed(task, error);
         return;
     }
@@ -1638,13 +1639,21 @@ static void file_xfer_read_cb(GObject *source_object,
     gssize count;
     GError *error = NULL;
 
+    task->pending = FALSE;
     count = g_input_stream_read_finish(G_INPUT_STREAM(task->file_stream),
                                        res, &error);
+    /* Check for pending earlier errors */
+    if (task->error) {
+        file_xfer_completed(task, error);
+        return;
+    }
+
     if (count > 0) {
         task->read_bytes += count;
         file_xfer_queue(task, count);
         file_xfer_flush_async(channel, task->cancellable,
                               file_xfer_data_flushed_cb, task);
+        task->pending = TRUE;
     } else if (error) {
         VDAgentFileXferStatusMessage msg = {
             .id = task->id,
@@ -1668,6 +1677,7 @@ static void file_xfer_continue_read(SpiceFileXferTask *task)
                               task->cancellable,
                               file_xfer_read_cb,
                               task);
+    task->pending = TRUE;
 }
 
 /* coroutine context */
@@ -2568,16 +2578,24 @@ void spice_main_set_display_enabled(SpiceMainChannel *channel, int id, gboolean
 
 static void file_xfer_completed(SpiceFileXferTask *task, GError *error)
 {
+    /* In case of multiple errors we only report the first error */
+    if (task->error)
+        g_clear_error(&error);
     if (error) {
         SPICE_DEBUG("File %s xfer failed: %s",
                     g_file_get_path(task->file), error->message);
         task->error = error;
     }
+
+    if (task->pending)
+        return;
+
     g_input_stream_close_async(G_INPUT_STREAM(task->file_stream),
                                G_PRIORITY_DEFAULT,
                                task->cancellable,
                                file_xfer_close_cb,
                                task);
+    task->pending = TRUE;
 }
 
 static void file_xfer_info_async_cb(GObject *obj, GAsyncResult *res, gpointer data)
@@ -2591,10 +2609,10 @@ 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;
 
+    task->pending = FALSE;
     info = g_file_query_info_finish(file, res, &error);
-    if (error)
+    if (error || task->error)
         goto failed;
 
     task->file_size =
@@ -2616,9 +2634,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),
@@ -2637,8 +2652,9 @@ static void file_xfer_read_async_cb(GObject *obj, GAsyncResult *res, gpointer da
     SpiceFileXferTask *task = (SpiceFileXferTask *)data;
     GError *error = NULL;
 
+    task->pending = FALSE;
     task->file_stream = g_file_read_finish(file, res, &error);
-    if (error) {
+    if (error || task->error) {
         file_xfer_completed(task, error);
         return;
     }
@@ -2650,6 +2666,7 @@ static void file_xfer_read_async_cb(GObject *obj, GAsyncResult *res, gpointer da
                             task->cancellable,
                             file_xfer_info_async_cb,
                             task);
+    task->pending = TRUE;
 }
 
 static void file_xfer_send_start_msg_async(SpiceMainChannel *channel,
@@ -2661,6 +2678,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 */
 
@@ -2675,12 +2693,15 @@ 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,
                       file_xfer_read_async_cb,
                       task);
-
+    task->pending = TRUE;
 }
 
 /**
commit 5cb25be544f132856498c3908a6f42146155a861
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 8 11:21:37 2013 +0100

    channel-main: Use file_xfer_completed where appropriate
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 10ba175..b0d60eb 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -163,6 +163,7 @@ static void migrate_channel_event_cb(SpiceChannel *channel, SpiceChannelEvent ev
 static gboolean main_migrate_handshake_done(gpointer data);
 static void spice_main_channel_send_migration_handshake(SpiceChannel *channel);
 static void file_xfer_continue_read(SpiceFileXferTask *task);
+static void file_xfer_completed(SpiceFileXferTask *task, GError *error);
 
 /* ------------------------------------------------------------------ */
 
@@ -1602,13 +1603,7 @@ static void file_xfer_data_flushed_cb(GObject *source_object,
     file_xfer_flush_finish(channel, res, &error);
 
     if (error != NULL) {
-        g_warning("failed to flush xfer queue: %s", error->message);
-        task->error = error;
-        g_input_stream_close_async(G_INPUT_STREAM(task->file_stream),
-                                   G_PRIORITY_DEFAULT,
-                                   task->cancellable,
-                                   file_xfer_close_cb,
-                                   task);
+        file_xfer_completed(task, error);
         return;
     }
 
@@ -1658,12 +1653,7 @@ static void file_xfer_read_cb(GObject *source_object,
         agent_msg_queue_many(task->channel, VD_AGENT_FILE_XFER_STATUS,
                              &msg, sizeof(msg), NULL);
         spice_channel_wakeup(SPICE_CHANNEL(task->channel), FALSE);
-        task->error = error;
-        g_input_stream_close_async(G_INPUT_STREAM(task->file_stream),
-                                   G_PRIORITY_DEFAULT,
-                                   task->cancellable,
-                                   file_xfer_close_cb,
-                                   task);
+        file_xfer_completed(task, error);
     }
     /* else EOF, do nothing (wait for VD_AGENT_FILE_XFER_STATUS from agent) */
 }
@@ -1687,6 +1677,7 @@ static void file_xfer_handle_status(SpiceMainChannel *channel,
     SpiceMainChannelPrivate *c = channel->priv;
     GList *l;
     SpiceFileXferTask *task;
+    GError *error = NULL;
 
     l = g_list_find_custom(c->file_xfer_task_list, &msg->id,
                            file_xfer_task_find);
@@ -1701,29 +1692,23 @@ static void file_xfer_handle_status(SpiceMainChannel *channel,
         file_xfer_continue_read(task);
         return;
     case VD_AGENT_FILE_XFER_STATUS_CANCELLED:
-        SPICE_DEBUG("user removed task %d, result: %d", msg->id,
-                    msg->result);
-        task->error = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
-                                  "transfer is cancelled by spice agent");
+        error = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+                            "transfer is cancelled by spice agent");
         break;
     case VD_AGENT_FILE_XFER_STATUS_ERROR:
-        task->error = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
-                                  "some errors occurred in the spice agent");
+        error = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+                            "some errors occurred in the spice agent");
         break;
     case VD_AGENT_FILE_XFER_STATUS_SUCCESS:
         break;
     default:
         g_warn_if_reached();
-        task->error = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
-                                  "unhandled status type: %u", msg->result);
+        error = g_error_new(SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
+                            "unhandled status type: %u", msg->result);
         break;
     }
 
-    g_input_stream_close_async(G_INPUT_STREAM(task->file_stream),
-                               G_PRIORITY_DEFAULT,
-                               task->cancellable,
-                               file_xfer_close_cb,
-                               task);
+    file_xfer_completed(task, error);
 }
 
 /* coroutine context */
commit 65eda3c93d5ee5f7681a44943e03f55c1d6f9afd
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 8 11:34:39 2013 +0100

    channel-main: file_xfer_failed -> file_xfer_completed
    
    Make file_xfer_failed usable for all file_stream closing.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index bd27ef4..10ba175 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -2581,12 +2581,13 @@ void spice_main_set_display_enabled(SpiceMainChannel *channel, int id, gboolean
     update_display_timer(channel, 1);
 }
 
-static void file_xfer_failed(SpiceFileXferTask *task, GError *error)
+static void file_xfer_completed(SpiceFileXferTask *task, GError *error)
 {
-    SPICE_DEBUG("File %s xfer failed: %s",
-                g_file_get_path(task->file), error->message);
-
-    task->error = error;
+    if (error) {
+        SPICE_DEBUG("File %s xfer failed: %s",
+                    g_file_get_path(task->file), error->message);
+        task->error = error;
+    }
     g_input_stream_close_async(G_INPUT_STREAM(task->file_stream),
                                G_PRIORITY_DEFAULT,
                                task->cancellable,
@@ -2642,7 +2643,7 @@ static void file_xfer_info_async_cb(GObject *obj, GAsyncResult *res, gpointer da
     return;
 
 failed:
-    file_xfer_failed(task, error);
+    file_xfer_completed(task, error);
 }
 
 static void file_xfer_read_async_cb(GObject *obj, GAsyncResult *res, gpointer data)
@@ -2653,7 +2654,7 @@ static void file_xfer_read_async_cb(GObject *obj, GAsyncResult *res, gpointer da
 
     task->file_stream = g_file_read_finish(file, res, &error);
     if (error) {
-        file_xfer_failed (task, error);
+        file_xfer_completed(task, error);
         return;
     }
 
commit 8fe3b38ca6cc0cc6f3bbeb3ab3d869328432326d
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Mar 7 14:55:14 2013 +0100

    channel-main: Make SpiceFileXferTask-s ref the channel
    
    So that the channel sticks around while their callbacks are completing.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 8e8a3a5..bd27ef4 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -1547,6 +1547,7 @@ static void file_xfer_task_free(SpiceFileXferTask *task)
     c = task->channel->priv;
     c->file_xfer_task_list = g_list_remove(c->file_xfer_task_list, task);
 
+    g_clear_object(&task->channel);
     g_clear_object(&task->file);
     g_clear_object(&task->file_stream);
     g_free(task);
@@ -2679,7 +2680,7 @@ static void file_xfer_send_start_msg_async(SpiceMainChannel *channel,
 
     task = spice_malloc0(sizeof(SpiceFileXferTask));
     task->id = ++xfer_id;
-    task->channel = channel;
+    task->channel = g_object_ref(channel);
     task->file = g_object_ref(file);
     task->flags = flags;
     task->cancellable = cancellable;
commit c3adb244259552b6cd528ab901e4d2334ca5b940
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 8 11:01:36 2013 +0100

    channel-main: Reset agent message receive state on agent stop
    
    Discard any partially received messages from the agent on agent stop.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 672fbcf..8e8a3a5 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -1362,11 +1362,8 @@ static void agent_start(SpiceMainChannel *channel)
 /* coroutine context  */
 static void agent_stopped(SpiceMainChannel *channel)
 {
-    SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv;
-
-    set_agent_connected(channel, FALSE);
-    c->agent_caps_received = false;
-    c->agent_display_config_sent = false;
+    spice_main_channel_reset_agent(channel);
+    set_agent_connected(channel, FALSE); /* For notify */
     emit_main_context(channel, SPICE_MAIN_AGENT_UPDATE);
 }
 
commit 081e41a21359ae9b73a33a067a830775d2d7d3b8
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 8 10:59:01 2013 +0100

    channel-main: Add a spice_main_channel_reset_agent helper function
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 4e766d3..672fbcf 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -327,22 +327,34 @@ static void spice_channel_iterate_write(SpiceChannel *channel)
 }
 
 /* main or coroutine context */
-static void spice_main_channel_reset(SpiceChannel *channel, gboolean migrating)
+static void spice_main_channel_reset_agent(SpiceMainChannel *channel)
 {
-    SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv;
+    SpiceMainChannelPrivate *c = channel->priv;
 
     c->agent_connected = FALSE;
     c->agent_caps_received = FALSE;
     c->agent_display_config_sent = FALSE;
-    c->agent_tokens = 0;
     c->agent_msg_pos = 0;
     g_free(c->agent_msg_data);
     c->agent_msg_data = NULL;
     c->agent_msg_size = 0;
+}
+
+/* main or coroutine context */
+static void spice_main_channel_reset(SpiceChannel *channel, gboolean migrating)
+{
+    SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv;
 
+    /* This is not part of reset_agent, since the spice-server expects any
+       pending multi-chunk messages to be completed by the client, even after
+       it has send an agent-disconnected msg as that is what the original
+       spicec did. Also see the TODO in server/reds.c reds_reset_vdp() */
+    c->agent_tokens = 0;
     agent_free_msg_queue(SPICE_MAIN_CHANNEL(channel));
     c->agent_msg_queue = g_queue_new();
 
+    spice_main_channel_reset_agent(SPICE_MAIN_CHANNEL(channel));
+
     SPICE_CHANNEL_CLASS(spice_main_channel_parent_class)->channel_reset(channel, migrating);
 }
 
commit 0563f1fcbf3a52f007101778c67b9c0d4ba405be
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 8 15:42:45 2013 +0100

    channel-main: Drop bogus xfer_id check from file_xfer_send_start_msg_async
    
    xfer_id > UINT32_MAX is never true since xfer_id is an uint32_t, and
    thus explicit wrapping is not necessary since it will wrap every
    UINT32_MAX + 1 itereations anyways.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 5d18366..4e766d3 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -2668,8 +2668,6 @@ static void file_xfer_send_start_msg_async(SpiceMainChannel *channel,
     SpiceFileXferTask *task;
     static uint32_t xfer_id;    /* Used to identify task id */
 
-    xfer_id = (xfer_id > UINT32_MAX) ? 0 : xfer_id;
-
     task = spice_malloc0(sizeof(SpiceFileXferTask));
     task->id = ++xfer_id;
     task->channel = channel;
commit f92612eb37f4e46632b62065222205a02313b122
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Sat Mar 9 11:50:19 2013 +0100

    channel-main: Properly verify result in spice_main_file_copy_finish
    
    Call g_simple_async_result_is_valid on the passed in result to verify it is
    what we expect.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 5f981c4..5d18366 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -1568,7 +1568,7 @@ static void file_xfer_close_cb(GObject      *object,
     res = g_simple_async_result_new(G_OBJECT(task->channel),
                                     task->callback,
                                     task->user_data,
-                                    file_xfer_continue_read);
+                                    spice_main_file_copy_async);
     if (task->error) {
         g_simple_async_result_take_error(res, task->error);
         g_simple_async_result_set_op_res_gboolean(res, FALSE);
@@ -2772,7 +2772,8 @@ gboolean spice_main_file_copy_finish(SpiceMainChannel *channel,
     GSimpleAsyncResult *simple;
 
     g_return_val_if_fail(SPICE_IS_MAIN_CHANNEL(channel), FALSE);
-    g_return_val_if_fail(result != NULL, FALSE);
+    g_return_val_if_fail(g_simple_async_result_is_valid(result,
+        G_OBJECT(channel), spice_main_file_copy_async), FALSE);
 
     simple = (GSimpleAsyncResult *)result;
 
commit 14fc12b844b29af47793c825fe798986e22c3abc
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 8 11:03:55 2013 +0100

    channel-main: Call g_simple_async_result_is_valid first
    
    Call g_simple_async_result_is_valid before using the result.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 257ded5..5f981c4 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -866,17 +866,15 @@ static void file_xfer_flush_async(SpiceMainChannel *channel, GCancellable *cance
 static gboolean file_xfer_flush_finish(SpiceMainChannel *channel, GAsyncResult *result,
                                        GError **error)
 {
-    GSimpleAsyncResult *simple;
+    GSimpleAsyncResult *simple = (GSimpleAsyncResult *)result;
 
-    simple = (GSimpleAsyncResult *)result;
+    g_return_val_if_fail(g_simple_async_result_is_valid(result,
+        G_OBJECT(channel), file_xfer_flush_async), FALSE);
 
     if (g_simple_async_result_propagate_error(simple, error)) {
         return FALSE;
     }
 
-    g_return_val_if_fail(g_simple_async_result_is_valid(result,
-        G_OBJECT(channel), file_xfer_flush_async), FALSE);
-
     CHANNEL_DEBUG(channel, "flushed finished!");
     return g_simple_async_result_get_op_res_gboolean(simple);
 }
commit d78e48fd618e96dae56d6a9c496c5387ad986c93
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Mar 8 16:04:18 2013 +0100

    Revert "channel-main: Fix dangling references to freed file-xfer-tasks on agent cancel"
    
    The fix from commit 19313a133af0d2404b29914b5937219127ad455b is incomplete,
    this commit added code to file_xfer_close_cb, to remove any reference to
    the task being closed from the flushing queue.
    
    But file_xfer_flushed / file_xfer_flush_async execute file_xfer_data_flushed_cb
    from an idle handler, so it is possible that when file_xfer_close_cb runs and
    frees the task, it is not part of the flushing queue, but a
    file_xfer_data_flushed_cb with the task as user_data argument still needs to
    run, and when it will run it will refer to the now freed task.
    
    A related problem which is also addressed in this patchset happens when we
    receive a file-xfer-cancel from the agent when an async operation on the
    file_stream is pending, since we then cannot call g_input_stream_close_async
    on it. This is fixed in the patchset by adding a pending flag to the task
    struct, and the problem with pending flushes is solved in the same way.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 78ece08..257ded5 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -1546,31 +1546,17 @@ static void file_xfer_task_free(SpiceFileXferTask *task)
 }
 
 /* main context */
-static void file_xfer_remove_flush(gpointer data, gpointer user_data)
-{
-    GAsyncResult *res = G_ASYNC_RESULT(data);
-    SpiceFileXferTask *task = user_data;
-    SpiceMainChannelPrivate *c = task->channel->priv;
-
-    if (g_async_result_get_user_data(res) == task) {
-        c->flushing = g_slist_remove(c->flushing, res);
-        g_object_unref(res);
-    }
-}
-
 static void file_xfer_close_cb(GObject      *object,
                                GAsyncResult *close_res,
                                gpointer      user_data)
 {
     GSimpleAsyncResult *res;
     SpiceFileXferTask *task;
-    SpiceMainChannelPrivate *c;
     GInputStream *stream = G_INPUT_STREAM(object);
     GError *error = NULL;
 
     stream = G_INPUT_STREAM(object);
     task = user_data;
-    c = task->channel->priv;
 
     g_input_stream_close_finish(stream, close_res, &error);
     if (error) {
@@ -1594,9 +1580,6 @@ static void file_xfer_close_cb(GObject      *object,
     g_simple_async_result_complete_in_idle(res);
     g_object_unref(res);
 
-    /* On agent cancel there may be pending flushes referencing this task */
-    g_slist_foreach(c->flushing, file_xfer_remove_flush, task);
-
     file_xfer_task_free(task);
 }
 
commit 118b33b40773c3b8bb420b5f9b36341b65376c9f
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Mar 7 14:34:12 2013 +0100

    spice-widget: Fix file drag-n-drop mime-type
    
    Currently the user can drag-drop text onto the widget, and it will try to
    open it as a file, not good, this fixes this.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c
index 6936ceb..011c905 100644
--- a/gtk/spice-widget.c
+++ b/gtk/spice-widget.c
@@ -537,7 +537,7 @@ static void spice_display_init(SpiceDisplay *display)
 {
     GtkWidget *widget = GTK_WIDGET(display);
     SpiceDisplayPrivate *d;
-    GtkTargetEntry targets = {"text/plain", 0, 0};
+    GtkTargetEntry targets = { "text/uri-list", 0, 0 };
 
     d = display->priv = SPICE_DISPLAY_GET_PRIVATE(display);
 


More information about the Spice-commits mailing list