[Spice-devel] [PATCH spice-gtk 02/15] channel-main: Fix dangling references to freed file-xfer-tasks on agent cancel
Hans de Goede
hdegoede at redhat.com
Sat Mar 9 03:06:22 PST 2013
While testing the agent error handling code I was triggering the
agent-file-xfer-cancel code-path in spice-gtk. This crashes due to the
flushing queue still having a reference to the task in question when its
gets cancelled from the agent side.
My previous fix for this added code to file_xfer_close_cb, to remove any
the task being closed from the flushing queue. Although this fixes my
test-case for this, on further thought this fix is not good enough.
The problem is that 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.
This new version of this patch fixes this by:
1) Passing the task id, rather then a pointer to file_xfer_data_flushed_cb
2) Let file_xfer_data_flushed_cb look up the id
3) If the id is not found exit without logging an error
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
gtk/channel-main.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index a1e1e1d..3a8229f 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -1558,12 +1558,26 @@ static void file_xfer_data_flushed_cb(GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
- SpiceFileXferTask *task = user_data;
+ SpiceFileXferTask *task;
SpiceMainChannel *channel = (SpiceMainChannel *)source_object;
GError *error = NULL;
+ uint32_t id = GPOINTER_TO_UINT(user_data);
+ GList *l;
+
+ /* We must do this before file_xfer_flush_finish(), because
+ file_xfer_flush_finish() may free the last channel reference */
+ l = g_list_find_custom(channel->priv->file_xfer_task_list, &id,
+ file_xfer_task_find);
file_xfer_flush_finish(channel, res, &error);
+ if (l == NULL) {
+ g_clear_error(&error);
+ return;
+ }
+
+ task = l->data;
+
if (error != NULL) {
g_warning("failed to flush xfer queue: %s", error->message);
task->error = error;
@@ -1612,7 +1626,8 @@ static void file_xfer_read_cb(GObject *source_object,
task->read_bytes += count;
file_xfer_queue(task, count);
file_xfer_flush_async(channel, task->cancellable,
- file_xfer_data_flushed_cb, task);
+ file_xfer_data_flushed_cb,
+ GUINT_TO_POINTER(task->id));
} else if (error) {
VDAgentFileXferStatusMessage msg = {
.id = task->id,
--
1.8.1.4
More information about the Spice-devel
mailing list