From 448ed75bd6c8db7ca48cab8aa1256a262e87fcc0 Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Mon, 11 Apr 2011 12:44:00 +0300 Subject: server: Add RedClient That means RedClient tracks a ring of channels. Right now there will be only a single client because of the disconnection mechanism - whenever a new client comes we disconnect all existing clients. But this patch adds already a ring of clients to reds.c (stored in RedServer). There is a known problem handling many connections and disconnections at the same time, trigerrable easily by the following script: export NEW_DISPLAY=:3.0 Xephyr $NEW_DISPLAY -noreset & for ((i = 0 ; i < 5; ++i)); do for ((j = 0 ; j < 10; ++j)); do DISPLAY=$NEW_DISPLAY c_win7x86_qxl_tests & done sleep 2; done I fixed a few of the problems resulting from this in the same patch. This required already introducing a few other changes: * make sure all removal of channels happens in the main thread, for that two additional dispatcher calls are added to remove a specific channel client (RED_WORKER_MESSAGE_CURSOR_DISCONNECT_CLIENT and RED_WORKER_MESSAGE_DISPLAY_DISCONNECT_CLIENT). * change some asserts in input channel. * make main channel disconnect not recursive * introduce disconnect call back to red_channel_create_parser The remaining abort is from a double free in the main channel, still can't find it (doesn't happen when running under valgrind - probably due to the slowness resulting from that), but is easy to see when running under gdb. --- server/inputs_channel.c | 59 ++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 25 deletions(-) (limited to 'server/inputs_channel.c') diff --git a/server/inputs_channel.c b/server/inputs_channel.c index e350689a..0fd4bd69 100644 --- a/server/inputs_channel.c +++ b/server/inputs_channel.c @@ -429,10 +429,16 @@ static void inputs_relase_keys(void) kbd_push_scan(keyboard, 0x38 | 0x80); //LALT } -static void inputs_channel_on_error(RedChannelClient *rcc) +static void inputs_channel_disconnect(RedChannelClient *rcc) { inputs_relase_keys(); - red_channel_client_destroy(rcc); + red_channel_client_disconnect(rcc); +} + +static void inputs_channel_on_error(RedChannelClient *rcc) +{ + red_printf(""); + inputs_channel_disconnect(rcc); } static void inputs_shutdown(Channel *channel) @@ -491,36 +497,39 @@ static void inputs_channel_hold_pipe_item(RedChannelClient *rcc, PipeItem *item) { } -static void inputs_link(Channel *channel, RedsStream *stream, int migration, +static void inputs_link(Channel *channel, RedClient *client, RedsStream *stream, int migration, int num_common_caps, uint32_t *common_caps, int num_caps, uint32_t *caps) { - InputsChannel *inputs_channel; RedChannelClient *rcc; - ASSERT(channel->data == NULL); - - red_printf("input channel create"); - g_inputs_channel = inputs_channel = (InputsChannel*)red_channel_create_parser( - sizeof(*inputs_channel), core, migration, FALSE /* handle_acks */ - ,inputs_channel_config_socket - ,spice_get_client_channel_parser(SPICE_CHANNEL_INPUTS, NULL) - ,inputs_channel_handle_parsed - ,inputs_channel_alloc_msg_rcv_buf - ,inputs_channel_release_msg_rcv_buf - ,inputs_channel_hold_pipe_item - ,inputs_channel_send_item - ,inputs_channel_release_pipe_item - ,inputs_channel_on_error - ,inputs_channel_on_error - ,NULL - ,NULL - ,NULL); - ASSERT(inputs_channel); + ASSERT(channel->data == g_inputs_channel); + + if (channel->data == NULL) { + red_printf("input channel create"); + g_inputs_channel = (InputsChannel*)red_channel_create_parser( + sizeof(InputsChannel), core, migration, FALSE /* handle_acks */ + ,inputs_channel_config_socket + ,inputs_channel_disconnect + ,spice_get_client_channel_parser(SPICE_CHANNEL_INPUTS, NULL) + ,inputs_channel_handle_parsed + ,inputs_channel_alloc_msg_rcv_buf + ,inputs_channel_release_msg_rcv_buf + ,inputs_channel_hold_pipe_item + ,inputs_channel_send_item + ,inputs_channel_release_pipe_item + ,inputs_channel_on_error + ,inputs_channel_on_error + ,NULL + ,NULL + ,NULL); + } + channel->data = g_inputs_channel; + ASSERT(g_inputs_channel); red_printf("input channel client create"); - rcc = red_channel_client_create(sizeof(RedChannelClient), &g_inputs_channel->base, stream); + rcc = red_channel_client_create(sizeof(RedChannelClient), &g_inputs_channel->base, + client, stream); ASSERT(rcc); - channel->data = inputs_channel; inputs_pipe_add_init(rcc); } -- cgit