From: Christophe Fergeau <cfergeau@xxxxxxxxxx> The file transfer code calls g_*_async() methods with a GTask as the user_data argument. It needs to own a reference to the GTask for the duration of the async call to keep the GTask alive, however it was never releasing it when it no longer needs it (that is, after calling g_task_return_*). Some of the leaks fixed by this patch are: * GTask leak after flush 11,232 bytes in 54 blocks are definitely lost in loss record 14,018 of 14,071 at 0x4C2BBAD: malloc (vg_replace_malloc.c:299) by 0xC14A0E8: g_malloc (gmem.c:94) by 0xC1608A2: g_slice_alloc (gslice.c:1025) by 0xC160ECD: g_slice_alloc0 (gslice.c:1051) by 0xBEDBD11: g_type_create_instance (gtype.c:1857) by 0xBEBD7DA: g_object_new_internal (gobject.c:1781) by 0xBEBF11C: g_object_newv (gobject.c:1928) by 0xBEBF89B: g_object_new (gobject.c:1621) by 0xBBA4424: g_task_new (gtask.c:693) by 0x6F8C3C0: file_xfer_flush_async (channel-main.c:899) by 0x6F8C3C0: file_xfer_read_async_cb (channel-main.c:1826) by 0xBBA3F38: g_task_return_now (gtask.c:1121) by 0xBBA4775: g_task_return (gtask.c:1179) * GTask leak from spice_main_file_copy_async() 208 bytes in 1 blocks are definitely lost in loss record 13,708 of 15,093 at 0x4C2BBAD: malloc (vg_replace_malloc.c:299) by 0xC14A0E8: g_malloc (gmem.c:94) by 0xC1608A2: g_slice_alloc (gslice.c:1025) by 0xC160ECD: g_slice_alloc0 (gslice.c:1051) by 0xBEDBD11: g_type_create_instance (gtype.c:1857) by 0xBEBD7DA: g_object_new_internal (gobject.c:1781) by 0xBEBF11C: g_object_newv (gobject.c:1928) by 0xBEBF89B: g_object_new (gobject.c:1621) by 0xBBA4424: g_task_new (gtask.c:693) by 0x6F8EF55: spice_main_file_copy_async (channel-main.c:3084) Signed-off-by: Victor Toso <victortoso@xxxxxxxxxx> --- src/channel-main.c | 2 ++ src/spice-file-transfer-task.c | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/src/channel-main.c b/src/channel-main.c index 26192ed..5af73b4 100644 --- a/src/channel-main.c +++ b/src/channel-main.c @@ -936,6 +936,7 @@ static void agent_send_msg_queue(SpiceMainChannel *channel) if (task) { /* if there's a flush task waiting for this message, finish it */ g_task_return_boolean(task, TRUE); + g_object_unref(task); g_hash_table_remove(c->flushing, out); } } @@ -2887,6 +2888,7 @@ static void file_transfer_operation_free(FileTransferOperation *xfer_op) SPICE_DEBUG("Transfer successful (%p)", xfer_op); g_task_return_boolean(xfer_op->task, TRUE); } + g_object_unref(xfer_op->task); /* SpiceFileTransferTask itself is freed after it emits "finish" */ g_hash_table_unref(xfer_op->xfer_task); diff --git a/src/spice-file-transfer-task.c b/src/spice-file-transfer-task.c index 23aab62..90c2a5d 100644 --- a/src/spice-file-transfer-task.c +++ b/src/spice-file-transfer-task.c @@ -118,9 +118,11 @@ static void spice_file_transfer_task_query_info_cb(GObject *obj, if (self->error) { /* Return error previously reported */ g_task_return_error(task, self->error); + g_object_unref(task); return; } else if (error) { g_task_return_error(task, error); + g_object_unref(task); return; } @@ -132,6 +134,7 @@ static void spice_file_transfer_task_query_info_cb(GObject *obj, g_object_notify(G_OBJECT(self), "progress"); g_task_return_pointer(task, info, g_object_unref); + g_object_unref(task); } static void spice_file_transfer_task_read_file_cb(GObject *obj, @@ -152,10 +155,12 @@ static void spice_file_transfer_task_read_file_cb(GObject *obj, /* Return error previously reported */ self->pending = FALSE; g_task_return_error(task, self->error); + g_object_unref(task); return; } else if (error) { self->pending = FALSE; g_task_return_error(task, error); + g_object_unref(task); return; } @@ -187,9 +192,11 @@ static void spice_file_transfer_task_read_stream_cb(GObject *source_object, if (self->error) { /* On any pending error on SpiceFileTransferTask */ g_task_return_error(task, self->error); + g_object_unref(task); return; } else if (error) { g_task_return_error(task, error); + g_object_unref(task); return; } @@ -209,6 +216,7 @@ static void spice_file_transfer_task_read_stream_cb(GObject *source_object, } g_task_return_int(task, nbytes); + g_object_unref(task); } /* main context */ @@ -433,6 +441,7 @@ void spice_file_transfer_task_read_async(SpiceFileTransferTask *self, * reach a state where agent says file-transfer SUCCEED but we are in a * PENDING state in SpiceFileTransferTask due reading in idle */ g_task_return_int(task, 0); + g_object_unref(task); return; } -- 2.7.4 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel