summaryrefslogtreecommitdiff
path: root/server/display-channel.c
diff options
context:
space:
mode:
authorFrediano Ziglio <fziglio@redhat.com>2015-12-09 13:34:15 +0000
committerFrediano Ziglio <fziglio@redhat.com>2015-12-10 17:36:25 +0000
commite7c79b71a40a6340849caa7f9345e3c8a7075664 (patch)
tree6fb2753c73daea8376c2458d5f50a5b5abb9edfb /server/display-channel.c
parentb12187b332123da383f52748e2865e0309d45d76 (diff)
channel: make sure we retain RedChannelClient while processing it
During display_channel_handle_migrate_data the pointer is passed to different functions which could release it making the pointer invalid. Make sure pointer is not freed while processing. Signed-off-by: Frediano Ziglio <fziglio@redhat.com> Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
Diffstat (limited to 'server/display-channel.c')
-rw-r--r--server/display-channel.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/server/display-channel.c b/server/display-channel.c
index e3131e01..7cbcea59 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -1190,6 +1190,7 @@ int display_channel_wait_for_migrate_data(DisplayChannel *display)
uint64_t end_time = red_get_monotonic_time() + DISPLAY_CLIENT_MIGRATE_DATA_TIMEOUT;
RedChannel *channel = &display->common.base;
RedChannelClient *rcc;
+ int ret = FALSE;
if (!red_channel_is_waiting_for_migrate_data(&display->common.base)) {
return FALSE;
@@ -1200,6 +1201,7 @@ int display_channel_wait_for_migrate_data(DisplayChannel *display)
rcc = SPICE_CONTAINEROF(ring_get_head(&channel->clients), RedChannelClient, channel_link);
+ red_channel_client_ref(rcc);
for (;;) {
red_channel_client_receive(rcc);
if (!red_channel_client_is_connected(rcc)) {
@@ -1207,7 +1209,8 @@ int display_channel_wait_for_migrate_data(DisplayChannel *display)
}
if (!red_channel_client_is_waiting_for_migrate_data(rcc)) {
- return TRUE;
+ ret = TRUE;
+ break;
}
if (red_get_monotonic_time() > end_time) {
spice_warning("timeout");
@@ -1216,7 +1219,8 @@ int display_channel_wait_for_migrate_data(DisplayChannel *display)
}
usleep(DISPLAY_CLIENT_RETRY_INTERVAL);
}
- return FALSE;
+ red_channel_client_unref(rcc);
+ return ret;
}
void display_channel_flush_all_surfaces(DisplayChannel *display)