[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