summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYonit Halperin <yhalperi@redhat.com>2012-08-06 14:14:09 +0300
committerYonit Halperin <yhalperi@redhat.com>2012-08-27 09:13:11 +0300
commit8874f3b259034dd3983c400d7ba918839b25ede8 (patch)
tree7ddefe41a09d7f651a2712bd2d3317bca8fc6b14
parent08d223beb39ee74422deaf04f7644ed795906720 (diff)
downloadspice-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.c27
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)