red-qxl: Avoid using dangling pointers to RedClient

A RedClient can be freed from the main thread following a main channel
disconnection (reds_client_disconnect). This can happen while another
thread is allocating a new channel client for that client.
To prevent the usage of a pointer which can be invalid
take ownership of the pointer.
Note that we don't need this when disconnecting as disconnection is
done synchronously (the dispatch messages are registered with
DISPATCH_ACK).

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
Acked-by: Christophe Fergeau <cfergeau@redhat.com>
This commit is contained in:
Frediano Ziglio 2017-08-24 14:33:03 +01:00
parent b496e4a037
commit 975d10c9ef
2 changed files with 8 additions and 2 deletions

View File

@ -83,7 +83,9 @@ static void red_qxl_set_display_peer(RedChannel *channel, RedClient *client,
spice_debug("%s", "");
dispatcher = (Dispatcher *)g_object_get_data(G_OBJECT(channel), "dispatcher");
payload.client = client;
// get a reference potentially the main channel can be destroyed in
// the main thread causing RedClient to be destroyed before using it
payload.client = g_object_ref(client);
payload.stream = stream;
payload.migration = migration;
red_channel_capabilities_init(&payload.caps, caps);
@ -141,7 +143,9 @@ static void red_qxl_set_cursor_peer(RedChannel *channel, RedClient *client, Reds
RedWorkerMessageCursorConnect payload = {0,};
Dispatcher *dispatcher = (Dispatcher *)g_object_get_data(G_OBJECT(channel), "dispatcher");
spice_printerr("");
payload.client = client;
// get a reference potentially the main channel can be destroyed in
// the main thread causing RedClient to be destroyed before using it
payload.client = g_object_ref(client);
payload.stream = stream;
payload.migration = migration;
red_channel_capabilities_init(&payload.caps, caps);

View File

@ -729,6 +729,7 @@ static void handle_dev_display_connect(void *opaque, void *payload)
dcc = dcc_new(display, msg->client, msg->stream, msg->migration, &msg->caps,
worker->image_compression, worker->jpeg_state, worker->zlib_glz_state);
g_object_unref(msg->client);
red_channel_capabilities_reset(&msg->caps);
if (!dcc) {
return;
@ -821,6 +822,7 @@ static void handle_dev_cursor_connect(void *opaque, void *payload)
cursor_channel_connect(worker->cursor_channel,
msg->client, msg->stream, msg->migration,
&msg->caps);
g_object_unref(msg->client);
red_channel_capabilities_reset(&msg->caps);
}