main: remove msg from c->flushing asap

The msg is no longer valid after spice_msg_out_send_internal(),
so it shouldn't be present in c->flushing since the same
memory can be assigned to a new message.

This currently causes issues when transferring multiple big
files at once (tested 4 × 200 MB).
The following can happen in agent_send_msg_queue(),
after msg is flushed:

(task1, task2 refers to two distinct SpiceFileTransferTasks,
 one per file)

g_task_return_boolean(task1) ->
file_xfer_data_flushed_cb(task1) ->
spice_file_transfer_task_read_async(task1) ->
g_coroutine_object_notify() [switches from coroutine context to main]
...
file_xfer_read_async_cb(task2) ->
file_xfer_queue_msg_to_agent(task2)
[allocates new msg for task2 at the same address as the old msg] ->
file_xfer_flush_async(task2)
[inserts to c->flushing, but the old msg is still present,
 so the data in the hash table changes from task1 to task2]
...
program returns to coroutine context,
g_task_return_boolean(task1) returns ->
g_hash_table_remove() [removes the entry that now contains task2]

Consequently, flush task for task2 never finishes
and it gets stuck.

This issue is present since 2261e50a64,
that replaced g_object_notify() in spice_file_transfer_task_read_async()
with g_coroutine_object_notify().

To solve it, remove the msg from c->flushing
before finishing the flush task.

Signed-off-by: Jakub Janků <jjanku@redhat.com>
This commit is contained in:
Jakub Janků 2019-12-29 16:35:13 +01:00 committed by Victor Toso
parent f851db2299
commit f784f4e6d1

View File

@ -944,9 +944,9 @@ static void agent_send_msg_queue(SpiceMainChannel *channel)
task = g_hash_table_lookup(c->flushing, out);
if (task) {
/* if there's a flush task waiting for this message, finish it */
g_hash_table_remove(c->flushing, out);
g_task_return_boolean(task, TRUE);
g_object_unref(task);
g_hash_table_remove(c->flushing, out);
}
}
if (g_queue_is_empty(c->agent_msg_queue) &&