From 785e59060c00129e47da6c0877604a56d7e0e32f Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Fri, 24 Apr 2020 17:45:49 +0200 Subject: [PATCH] xwayland: Fix infinite loop at startup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mutter recently added headless tests, and when running those tests the Wayland compositor runs for a very short time. Xwayland is spawned by the Wayland compositor and upon startup will query the various Wayland protocol supported by the compositor. To do so, it will do a roundtrip to the Wayland server waiting for events it expects. If the Wayland compositor terminates before Xwayland has got the replies it expects, it will loop indefinitely calling `wl_display_roundtrip()` continuously. To avoid that issue, add a new `xwl_screen_roundtrip()` that checks for the returned value from `wl_display_roundtrip()` and fails if it is negative. Signed-off-by: Olivier Fourdan Reviewed-by: Roman Gilg Reviewed-by: Jonas Ã…dahl --- hw/xwayland/xwayland-input.c | 4 +--- hw/xwayland/xwayland-screen.c | 26 +++++++++++++++----------- hw/xwayland/xwayland-screen.h | 1 + 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index beaac192f..ba7c6631f 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -2915,9 +2915,7 @@ InitInput(int argc, char *argv[]) xwl_screen->XYToWindow = pScreen->XYToWindow; pScreen->XYToWindow = xwl_xy_to_window; - wl_display_roundtrip(xwl_screen->display); - while (xwl_screen->expecting_event) - wl_display_roundtrip(xwl_screen->display); + xwl_screen_roundtrip(xwl_screen); } void diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c index 9f275b540..2d82c61af 100644 --- a/hw/xwayland/xwayland-screen.c +++ b/hw/xwayland/xwayland-screen.c @@ -489,6 +489,19 @@ xwl_sync_events (struct xwl_screen *xwl_screen) xwl_read_events (xwl_screen); } +void +xwl_screen_roundtrip(struct xwl_screen *xwl_screen) +{ + int ret; + + ret = wl_display_roundtrip(xwl_screen->display); + while (ret >= 0 && xwl_screen->expecting_event) + ret = wl_display_roundtrip(xwl_screen->display); + + if (ret < 0) + xwl_give_up("could not connect to wayland server\n"); +} + Bool xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) { @@ -572,14 +585,7 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) xwl_screen->registry = wl_display_get_registry(xwl_screen->display); wl_registry_add_listener(xwl_screen->registry, ®istry_listener, xwl_screen); - ret = wl_display_roundtrip(xwl_screen->display); - if (ret == -1) { - ErrorF("could not connect to wayland server\n"); - return FALSE; - } - - while (xwl_screen->expecting_event > 0) - wl_display_roundtrip(xwl_screen->display); + xwl_screen_roundtrip(xwl_screen); bpc = xwl_screen->depth / 3; green_bpc = xwl_screen->depth - 2 * bpc; @@ -678,9 +684,7 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) AddCallback(&PropertyStateCallback, xwl_property_callback, pScreen); - wl_display_roundtrip(xwl_screen->display); - while (xwl_screen->expecting_event) - wl_display_roundtrip(xwl_screen->display); + xwl_screen_roundtrip(xwl_screen); return ret; } diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h index 69f42bd76..8d0b12705 100644 --- a/hw/xwayland/xwayland-screen.h +++ b/hw/xwayland/xwayland-screen.h @@ -126,6 +126,7 @@ struct xwl_output *xwl_screen_get_first_output(struct xwl_screen *xwl_screen); Bool xwl_close_screen(ScreenPtr screen); Bool xwl_screen_init(ScreenPtr pScreen, int argc, char **argv); void xwl_sync_events (struct xwl_screen *xwl_screen); +void xwl_screen_roundtrip (struct xwl_screen *xwl_screen); void xwl_surface_damage(struct xwl_screen *xwl_screen, struct wl_surface *surface, int32_t x, int32_t y, int32_t width, int32_t height);