diff options
author | Yonit Halperin <yhalperi@redhat.com> | 2012-08-06 14:14:09 +0300 |
---|---|---|
committer | Yonit Halperin <yhalperi@redhat.com> | 2012-08-27 09:13:11 +0300 |
commit | 8874f3b259034dd3983c400d7ba918839b25ede8 (patch) | |
tree | 7ddefe41a09d7f651a2712bd2d3317bca8fc6b14 | |
parent | 08d223beb39ee74422deaf04f7644ed795906720 (diff) | |
download | spice-8874f3b259034dd3983c400d7ba918839b25ede8.tar.gz spice-8874f3b259034dd3983c400d7ba918839b25ede8.tar.xz spice-8874f3b259034dd3983c400d7ba918839b25ede8.zip |
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).
-rw-r--r-- | server/snd_worker.c | 27 |
1 files 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) |