Fix XWayland crash: switch to lazy mode

XWayland was started eagerly (at compositor init) which caused a
segfault when XWayland couldn't connect back to the Wayland socket
(race condition in nested mode). Since the WM UI is now pure Wayland
(no X11 rendering), XWayland is only needed for X11 client apps.

Switch to lazy mode: XWayland starts only when the first X11 client
connects. This eliminates the startup wait loop and the associated
crash. Also set xwayland_ready=true in the server destroy handler
as a safety net.
This commit is contained in:
Levi Neely 2026-05-13 14:16:47 +02:00
parent faf4c76085
commit 7e1da342be
1 changed files with 7 additions and 8 deletions

View File

@ -1349,6 +1349,7 @@ handle_xwayland_server_destroy(struct wl_listener *listener, void *data)
(void)listener;
(void)data;
wwarning("wl_backend: XWayland server exited");
wl_state.xwayland_ready = true; /* break the wait loop */
}
static void
@ -2402,7 +2403,7 @@ wl_display_open(const char *name)
* renders through XWayland, making the WM visible on-screen.
* The ready signal fires once Xwayland's socket accepts connections. */
wl_state.xwayland = wlr_xwayland_create(wl_state.display,
wl_state.compositor, false);
wl_state.compositor, true);
if (wl_state.xwayland) {
/* Wire server destroy signal to detect early failure (e.g. stale
* display lock → Xwayland exits before ready fires). */
@ -2492,14 +2493,12 @@ wl_display_open(const char *name)
* handle_xwayland_ready() calls XOpenDisplay and stores the result in
* wl_state.x_display, then sets xwayland_ready = true to break the loop.
* If XWayland is not available, return NULL (pure Wayland path). */
/* XWayland is lazy — it starts when the first X11 client connects.
* No need to wait for it at startup. Mark as ready so the rest of
* init proceeds without blocking. */
if (wl_state.xwayland) {
wwarning("wl_backend: waiting for XWayland ready signal...");
struct wl_event_loop *ev_loop =
wl_display_get_event_loop(wl_state.display);
while (!wl_state.xwayland_ready) {
wl_display_flush_clients(wl_state.display);
wl_event_loop_dispatch(ev_loop, 10);
}
wwarning("wl_backend: XWayland configured (lazy mode) — starts on first X11 client");
wl_state.xwayland_ready = true;
if (wl_state.x_display) {
wwarning("wl_backend: XWayland bridge ready — Display*=%p, full WM UI enabled",
(void *)wl_state.x_display);