[PATCH xwayland v2] xwayland: do not add output into output_list multiple times

Marek Chalupa mchqwerty at gmail.com
Thu May 21 06:43:43 PDT 2015


output.done event can be sent even on some property change, not only
when announcing the output. Therefore we must check if we already have it
otherwise we may corrupt the list by adding it multiple times.

This fixes bug when xwayland looped indefinitely in output.done handler
and that can be reproduced following these steps (under X without
multi-monitor setup):
 1) run weston --output-count=2
 2) run xterm, move it so that half is on one output
    and half on the other
 3) close second output, try run weston-terminal

weston sends updated outputs which trigger this bug.

v2. factor out common code into function
    move expecting_events into right branch

Signed-off-by: Marek Chalupa <mchqwerty at gmail.com>
---
 hw/xwayland/xwayland-output.c | 42 ++++++++++++++++++++++++++++++------------
 1 file changed, 30 insertions(+), 12 deletions(-)

diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c
index 155cbc1..8949930 100644
--- a/hw/xwayland/xwayland-output.c
+++ b/hw/xwayland/xwayland-output.c
@@ -113,29 +113,47 @@ output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags,
                  xwl_output->rotation, NULL, 1, &xwl_output->randr_output);
 }
 
+static inline void
+output_get_new_size(struct xwl_output *xwl_output,
+		    int *height, int *width)
+{
+    if (*width < xwl_output->x + xwl_output->width)
+        *width = xwl_output->x + xwl_output->width;
+
+    if (*height < xwl_output->y + xwl_output->height)
+        *height = xwl_output->y + xwl_output->height;
+}
+
 static void
 output_handle_done(void *data, struct wl_output *wl_output)
 {
-    struct xwl_output *xwl_output = data;
+    struct xwl_output *it, *xwl_output = data;
     struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
-    int width, height;
+    int width = 0, height = 0, has_this_output = 0;
 
-    xorg_list_append(&xwl_output->link, &xwl_screen->output_list);
+    xorg_list_for_each_entry(it, &xwl_screen->output_list, link) {
+        /* output done event is sent even when some property
+         * of output is changed. That means that we may already
+         * have this output. If it is true, we must not add it
+         * into the output_list otherwise we'll corrupt it */
+        if (it == xwl_output)
+            has_this_output = 1;
 
-    width = 0;
-    height = 0;
-    xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) {
-        if (width < xwl_output->x + xwl_output->width)
-            width = xwl_output->x + xwl_output->width;
-        if (height < xwl_output->y + xwl_output->height)
-            height = xwl_output->y + xwl_output->height;
+        output_get_new_size(it, &height, &width);
+    }
+
+    if (!has_this_output) {
+        xorg_list_append(&xwl_output->link, &xwl_screen->output_list);
+
+        /* we did not check this output for new screen size, do it now */
+        output_get_new_size(xwl_output, &height, &width);
+
+	--xwl_screen->expecting_event;
     }
 
     xwl_screen->width = width;
     xwl_screen->height = height;
     RRScreenSizeNotify(xwl_screen->screen);
-
-    xwl_screen->expecting_event--;
 }
 
 static void
-- 
2.1.0



More information about the wayland-devel mailing list