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

Marek Chalupa mchqwerty at gmail.com
Wed Jul 15 03:22:33 PDT 2015



On 05/21/2015 03:43 PM, Marek Chalupa wrote:
> 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
>

ping


More information about the xorg-devel mailing list