summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2011-12-18 11:12:56 +0100
committerHans de Goede <hdegoede@redhat.com>2011-12-18 11:20:12 +0100
commitffc4de01e6f9ea0676f17b10e45a137d7e15d6ac (patch)
treef4a564babb8c2990764e1b3756dac333aad3157a
parentcf21af1846939ba9bb2927f63433125ed9c8fbb0 (diff)
downloadspice-ffc4de01e6f9ea0676f17b10e45a137d7e15d6ac.tar.gz
spice-ffc4de01e6f9ea0676f17b10e45a137d7e15d6ac.tar.xz
spice-ffc4de01e6f9ea0676f17b10e45a137d7e15d6ac.zip
spicevmc: Fix assert when still connected on session disconnect (fdo#43903)
Currently when the main channel disconnects while a spicevmc channel (such as a usbredir channel) is still connected, qemu will abort with the following message: ring_remove: ASSERT item->next != NULL && item->prev != NULL failed This is caused by red_client_destroy() first calling: rcc->channel->client_cbs.disconnect(rcc); And then calling: red_channel_client_destroy(rcc); For each channel. This is fine, but the spicevmc disconnect code does a red_channel_client_destroy(rcc) itself since as usb devices are added / removed, the channels carrying their traffic get connected / disconnected and they get re-used for new devices, which won't work if the old channel is still there when the new connection comes in. This patch fixes the double destroy when there are still spicevmc channels connected by not doing the red_channel_client_destroy from the spicevmc disconnect code when not just the channel, but the entire client is disconnecting. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r--server/spicevmc.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/server/spicevmc.c b/server/spicevmc.c
index 85809840..b1a7d8dc 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -99,7 +99,11 @@ static void spicevmc_red_channel_client_on_disconnect(RedChannelClient *rcc)
sin = state->chardev_sin;
sif = SPICE_CONTAINEROF(sin->base.sif, SpiceCharDeviceInterface, base);
- red_channel_client_destroy(rcc);
+ /* Don't destroy the rcc if the entire client is disconnecting, as then
+ red_client_destroy will already do this! */
+ if (!rcc->client->disconnecting)
+ red_channel_client_destroy(rcc);
+
state->rcc = NULL;
if (sif->state) {
sif->state(sin, 0);