From d691602784b3592fdd4e2e54cddc29f53fafdfef Mon Sep 17 00:00:00 2001 From: Yonit Halperin Date: Thu, 24 May 2012 11:05:58 +0300 Subject: server/red_worker: fix red_wait_pipe_item_sent Resolves: rhbz#824384 red_wait_pipe_item_sent mistakingly returned without waiting for sending the given pipe item when the channel wasn't blocked. As a result, we failed when we had to destroy a surface (e.g., QXL_IO_DESTROY_ALL_SURFACES) and to release all the drawables that are depended on it (by removing them or waiting they will be sent). In addition, red_wait_pipe_item_sent increased and decreased the reference to the pipe item using channel_cbs->hold_item, and channel_cbs->release_item. However, these calls can be called only by red_channel, otherwise display_channel_client_release_item_before_push is called twice and leads to a double call to ring_remove(&dpi->base). Instead ref/put_drawable_pipe_item should be called. --- server/red_worker.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/server/red_worker.c b/server/red_worker.c index 2709486..c712180 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -1998,6 +1998,7 @@ static void red_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int } if (depend_found) { + spice_debug("surface %d dependent item found %p, %p", surface_id, drawable, item); if (force) { break; } else { @@ -10334,16 +10335,13 @@ static void red_wait_outgoing_items(RedChannel *channel) /* TODO: more evil sync stuff. anything with the word wait in it's name. */ static void red_wait_pipe_item_sent(RedChannelClient *rcc, PipeItem *item) { - RedChannel *channel = rcc->channel; + DrawablePipeItem *dpi; uint64_t end_time; int item_in_pipe; - if (!red_channel_client_blocked(rcc)) { - return; - } - spice_printerr(""); - channel->channel_cbs.hold_item(rcc, item); + dpi = SPICE_CONTAINEROF(item, DrawablePipeItem, dpi_pipe_item); + ref_drawable_pipe_item(dpi); end_time = red_now() + CHANNEL_PUSH_TIMEOUT; @@ -10366,7 +10364,7 @@ static void red_wait_pipe_item_sent(RedChannelClient *rcc, PipeItem *item) } else { red_wait_outgoing_item(rcc); } - channel->channel_cbs.release_item(rcc, item, FALSE); + put_drawable_pipe_item(dpi); } static void surface_dirty_region_to_rects(RedSurface *surface, -- cgit v1.2.3