summaryrefslogtreecommitdiffstats
path: root/server/red_channel.c
diff options
context:
space:
mode:
authorYonit Halperin <yhalperi@redhat.com>2012-08-06 14:04:38 +0300
committerYonit Halperin <yhalperi@redhat.com>2012-08-27 09:13:11 +0300
commit08d223beb39ee74422deaf04f7644ed795906720 (patch)
tree5ecbd4a4e97bcbec7ff4dce75f4def4606f3ebb9 /server/red_channel.c
parent8e7b22b7861d2859167767822f29749bfe3ecc16 (diff)
downloadspice-08d223beb39ee74422deaf04f7644ed795906720.tar.gz
spice-08d223beb39ee74422deaf04f7644ed795906720.tar.xz
spice-08d223beb39ee74422deaf04f7644ed795906720.zip
red_channel (dummy): fix not adding dummy RedChannelClient to the client
snd channel wasn't added to be part of the client's channels list. As a result, when the client was destroyed, or migrated, snd channel client wasn't destroy, or its migration callback wasn't called. However, due to adding dummy channels to the client, we need special handling for calls to disconnecting dummy channel clients. TODO: we need to refactor snd_worker to use red_channel
Diffstat (limited to 'server/red_channel.c')
-rw-r--r--server/red_channel.c34
1 files changed, 23 insertions, 11 deletions
diff --git a/server/red_channel.c b/server/red_channel.c
index 803804e1..18b69d32 100644
--- a/server/red_channel.c
+++ b/server/red_channel.c
@@ -998,9 +998,7 @@ static void red_channel_client_unref(RedChannelClient *rcc)
void red_channel_client_destroy(RedChannelClient *rcc)
{
rcc->destroying = 1;
- if (red_channel_client_is_connected(rcc)) {
- red_channel_client_disconnect(rcc);
- }
+ red_channel_client_disconnect(rcc);
red_client_remove_channel(rcc);
red_channel_client_unref(rcc);
}
@@ -1370,7 +1368,11 @@ void red_channel_pipes_add_empty_msg(RedChannel *channel, int msg_type)
int red_channel_client_is_connected(RedChannelClient *rcc)
{
- return rcc->stream != NULL;
+ if (!rcc->dummy) {
+ return rcc->stream != NULL;
+ } else {
+ return rcc->dummy_connected;
+ }
}
int red_channel_is_connected(RedChannel *channel)
@@ -1429,10 +1431,23 @@ static void red_client_remove_channel(RedChannelClient *rcc)
pthread_mutex_unlock(&rcc->client->lock);
}
+static void red_channel_client_disconnect_dummy(RedChannelClient *rcc)
+{
+ spice_assert(rcc->dummy);
+ if (ring_item_is_linked(&rcc->channel_link)) {
+ red_channel_remove_client(rcc);
+ }
+ rcc->dummy_connected = FALSE;
+}
+
void red_channel_client_disconnect(RedChannelClient *rcc)
{
spice_printerr("%p (channel %p type %d id %d)", rcc, rcc->channel,
rcc->channel->type, rcc->channel->id);
+ if (rcc->dummy) {
+ red_channel_client_disconnect_dummy(rcc);
+ return;
+ }
if (!red_channel_client_is_connected(rcc)) {
return;
}
@@ -1490,8 +1505,12 @@ RedChannelClient *red_channel_client_create_dummy(int size,
rcc->incoming.header.data = rcc->incoming.header_buf;
rcc->incoming.serial = 1;
+ ring_init(&rcc->pipe);
+ rcc->dummy = TRUE;
+ rcc->dummy_connected = TRUE;
red_channel_add_client(channel, rcc);
+ red_client_add_channel(client, rcc);
pthread_mutex_unlock(&client->lock);
return rcc;
error:
@@ -1499,13 +1518,6 @@ error:
return NULL;
}
-void red_channel_client_destroy_dummy(RedChannelClient *rcc)
-{
- red_channel_remove_client(rcc);
- red_channel_client_destroy_remote_caps(rcc);
- free(rcc);
-}
-
void red_channel_apply_clients(RedChannel *channel, channel_client_callback cb)
{
RingItem *link;