[Spice-devel] [PATCH spice-gtk 2/3] decode-glz: Handle needing glz images before they have arrived

Hans de Goede hdegoede at redhat.com
Fri Oct 7 05:24:55 PDT 2011


With multi monitor guests, it is possible for a glz-image to refer to
bits from another glz-image which has not arrived yet! This can happen
because each monitor has its own display channel, and thus its own socket,
but they share the glz dict. Thus things can arrive out of order, with a
glz-image on display 1 arriving before the glz-image on display 2 which it
refers too.

This triggers the:
g_return_val_if_fail(w->images[slot]->hdr.id == id - dist, NULL);

In glz_decoder_window_bits(), which is what caused me to debug this, once
the out order thing was clear, so was the fix.
If w->images[slot]->hdr.id == id - dist is not true, we need to wait for the
correct image to arrive.

The out of order issue with multiple monitors can also trigger the
g_warn_if_reached() in glz_decoder_window_resize(), so remove that.

Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 gtk/decode-glz.c |   21 ++++++++++++---------
 1 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/gtk/decode-glz.c b/gtk/decode-glz.c
index 8ddb9d8..317fa9e 100644
--- a/gtk/decode-glz.c
+++ b/gtk/decode-glz.c
@@ -95,8 +95,12 @@ static void glz_decoder_window_resize(SpiceGlzDecoderWindow *w)
     new_images = spice_new0(struct glz_image*, w->nimages * 2);
     for (i = 0; i < w->nimages; i++) {
         if (w->images[i] == NULL) {
-            /* FIXME: is this really an anormal condition? */
-            g_warn_if_reached();
+            /*
+             * We can have empty slots when images come in out of order, this
+             * can happen when a vm has multiple displays, since each display
+             * uses its own socket there is no guarantee that images
+             * originating from different displays are received in id order.
+             */
             continue;
         }
         new_slot = w->images[i]->hdr.id % (w->nimages * 2);
@@ -124,14 +128,14 @@ static void glz_decoder_window_add(SpiceGlzDecoderWindow *w,
 struct wait_for_image_data {
     SpiceGlzDecoderWindow     *window;
     uint64_t                   id;
-    uint32_t                   dist;
 };
 
 static gboolean wait_for_image(gpointer data)
 {
     struct wait_for_image_data *wait = data;
-    int slot = (wait->id - wait->dist) % wait->window->nimages;
-    gboolean ready = wait->window->images[slot] != NULL;
+    int slot = wait->id % wait->window->nimages;
+    struct glz_image *image = wait->window->images[slot];
+    gboolean ready = image && image->hdr.id == wait->id;
 
     SPICE_DEBUG("image with slot %d: %s", slot, ready ? "yes" : "no");
 
@@ -142,12 +146,11 @@ static void *glz_decoder_window_bits(SpiceGlzDecoderWindow *w, uint64_t id,
                                      uint32_t dist, uint32_t offset)
 {
     int slot = (id - dist) % w->nimages;
-    
-    if (!w->images[slot]) {
+
+    if (!w->images[slot] || w->images[slot]->hdr.id != id - dist) {
         struct wait_for_image_data data = {
             .window = w,
-            .id = id,
-            .dist = dist,
+            .id = id - dist,
         };
 
         g_condition_wait(wait_for_image, &data);
-- 
1.7.6.4



More information about the Spice-devel mailing list