From 8874f3b259034dd3983c400d7ba918839b25ede8 Mon Sep 17 00:00:00 2001 From: Yonit Halperin Date: Mon, 6 Aug 2012 14:14:09 +0300 Subject: snd_channel: fix double release Due to the fix in the previous patch, snd_disconnect_channel can be called both when there is write/read error in the channel, or from red_client_destroy (which calls client_cbs.disconnect). Multiple calls to snd_disconnect_channel resulted in calling channel->cleanup(channel) more than once (double release). --- server/snd_worker.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/server/snd_worker.c b/server/snd_worker.c index 2746940f..bcf14529 100644 --- a/server/snd_worker.c +++ b/server/snd_worker.c @@ -219,15 +219,20 @@ static void snd_disconnect_channel(SndChannel *channel) SndWorker *worker; if (!channel) { + spice_debug("not connected"); return; } - channel->cleanup(channel); - worker = channel->worker; - red_channel_client_disconnect(worker->connection->channel_client); - core->watch_remove(channel->stream->watch); - channel->stream->watch = NULL; - reds_stream_free(channel->stream); - spice_marshaller_destroy(channel->send_data.marshaller); + spice_debug("%p", channel); + if (channel->stream) { + channel->cleanup(channel); + worker = channel->worker; + red_channel_client_disconnect(worker->connection->channel_client); + core->watch_remove(channel->stream->watch); + channel->stream->watch = NULL; + reds_stream_free(channel->stream); + channel->stream = NULL; + spice_marshaller_destroy(channel->send_data.marshaller); + } snd_channel_put(channel); } @@ -992,13 +997,15 @@ static void snd_disconnect_channel_client(RedChannelClient *rcc) { SndWorker *worker; + spice_debug(NULL); spice_assert(rcc->channel); spice_assert(rcc->channel->data); worker = (SndWorker *)rcc->channel->data; - spice_assert(worker->connection->channel_client == rcc); - snd_disconnect_channel(worker->connection); - spice_assert(worker->connection == NULL); + if (worker->connection) { + spice_assert(worker->connection->channel_client == rcc); + snd_disconnect_channel(worker->connection); + } } static void snd_set_command(SndChannel *channel, uint32_t command) -- cgit