wayland: Phase 21 — lazy XWayland + lock file cleanup on shutdown
Switch wlr_xwayland_create from lazy=false to lazy=true. With eager
start the Xwayland process forks before the compositor's event loop is
running; Xwayland's Wayland client tries to negotiate globals immediately,
gets no response, and closes its connection ("Broken pipe" / "xcb connect
failed: 1"). Lazy mode defers the fork until the first X11 client
connects, by which time the event loop is fully running.
The pre-allocated display number is still available immediately so DISPLAY
is set for child processes regardless of whether Xwayland has started.
On shutdown, after SIGKILL-ing the Xwayland process, explicitly remove
/tmp/.X{n}-lock and /tmp/.X11-unix/X{n}. Without this, if the dead
process's PID is reused by another process before the next wmaker run,
wlroots' stale-lock detection (kill(old_pid,0)) wrongly reports the
display as in-use and the next run fails to claim the same display number.
Smoke test updated: check for "XWayland DISPLAY=.*lazy" instead of the
old "XWayland started DISPLAY=" pattern.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
aa294ed13c
commit
632c093355
|
|
@ -1301,11 +1301,16 @@ wl_display_open(const char *name)
|
|||
wl_signal_add(&wl_state.xdg_shell->events.new_surface,
|
||||
&wl_state.xdg_new_surface_listener);
|
||||
|
||||
/* Phase 17: start XWayland so X11 clients (e.g. GNUstep apps) can run
|
||||
* under the Wayland compositor. The third argument (lazy=false) starts
|
||||
* the Xwayland process eagerly so DISPLAY is available immediately. */
|
||||
/* Phase 17: register XWayland for X11 client support.
|
||||
* Using lazy=true: the Xwayland process does NOT start at compositor
|
||||
* boot. It starts automatically on the first X11 client connect.
|
||||
* This avoids a startup race where Xwayland's Wayland client tries to
|
||||
* negotiate globals before the compositor's event loop is running,
|
||||
* causing "Broken pipe" and "xcb connect failed" on the first frame.
|
||||
* The display number is pre-allocated immediately so DISPLAY can be
|
||||
* set for child processes even before any X11 client connects. */
|
||||
wl_state.xwayland = wlr_xwayland_create(wl_state.display,
|
||||
wl_state.compositor, false);
|
||||
wl_state.compositor, true);
|
||||
if (wl_state.xwayland) {
|
||||
wl_state.xwayland_new_surface_listener.notify = handle_xwayland_new_surface;
|
||||
wl_signal_add(&wl_state.xwayland->events.new_surface,
|
||||
|
|
@ -1313,7 +1318,7 @@ wl_display_open(const char *name)
|
|||
wlr_xwayland_set_seat(wl_state.xwayland, wl_state.seat);
|
||||
if (wl_state.xwayland->display_name) {
|
||||
setenv("DISPLAY", wl_state.xwayland->display_name, 1);
|
||||
wwarning("wl_backend: XWayland started DISPLAY=%s",
|
||||
wwarning("wl_backend: XWayland DISPLAY=%s (lazy: starts on first X11 client)",
|
||||
wl_state.xwayland->display_name);
|
||||
} else {
|
||||
wwarning("wl_backend: XWayland created (display_name pending)");
|
||||
|
|
@ -1405,6 +1410,7 @@ wl_display_close(void)
|
|||
* still valid because the event loop is stopped and the socket closure
|
||||
* has not been dispatched, so wlroots' wl_client_destroy() succeeds. */
|
||||
if (wl_state.xwayland->server) {
|
||||
int xdisp = wl_state.xwayland->server->display;
|
||||
if (wl_state.xwayland->server->pid > 0)
|
||||
kill(wl_state.xwayland->server->pid, SIGKILL);
|
||||
/* wlroots 0.15 bug: after any Wayland client has connected and
|
||||
|
|
@ -1417,6 +1423,17 @@ wl_display_close(void)
|
|||
* clean it up; if it is stale, it has already been removed from
|
||||
* the display's client list and nothing more is needed. */
|
||||
wl_state.xwayland->server->client = NULL;
|
||||
/* Clean up X lock file and Unix socket left by SIGKILL'd Xwayland.
|
||||
* Without this, the next run may find a stale lock file whose PID
|
||||
* has been reused by an unrelated process, causing wlroots to
|
||||
* refuse to reclaim the display number → "xcb connect failed". */
|
||||
{
|
||||
char path[64];
|
||||
snprintf(path, sizeof(path), "/tmp/.X%d-lock", xdisp);
|
||||
unlink(path);
|
||||
snprintf(path, sizeof(path), "/tmp/.X11-unix/X%d", xdisp);
|
||||
unlink(path);
|
||||
}
|
||||
}
|
||||
wl_state.xwayland = NULL;
|
||||
unsetenv("DISPLAY");
|
||||
|
|
|
|||
|
|
@ -118,10 +118,11 @@
|
|||
# so handle_backend_new_output finds a valid scene when it fires.
|
||||
# Verified by "scene graph created" + "scene output created" +
|
||||
# "headless compositor mode" logs.
|
||||
# 39. (Phase 17) XWayland started: wlr_xwayland_create() is called in
|
||||
# wl_display_open(); compositor logs "XWayland started DISPLAY=:<n>"
|
||||
# so X11 clients (GNUstep apps) can connect. DISPLAY env var is set.
|
||||
# Verified by "XWayland started DISPLAY=" log.
|
||||
# 39. (Phase 17) XWayland display allocated (lazy start): wlr_xwayland_create()
|
||||
# is called with lazy=true; Xwayland only starts on first X11 client.
|
||||
# Compositor logs "XWayland DISPLAY=:<n> (lazy: starts on first X11 client)".
|
||||
# DISPLAY env var is set from the pre-allocated display number.
|
||||
# Verified by "XWayland DISPLAY=.*lazy" log.
|
||||
# 38. (Phase 11) noclip/nodock set in wl_screen_create_internals: wDockCreate
|
||||
# requires X11 rendering resources unavailable in Wayland mode; disabling
|
||||
# the dock/clip prevents crashes when wWorkspaceNew is called to create
|
||||
|
|
@ -267,14 +268,16 @@ grep -q 'dock/clip disabled in Wayland mode' /tmp/wl-smoke-stderr \
|
|||
|| die "compositor did not log dock/clip disabled (noclip/nodock not set in wl_screen_create_internals)"
|
||||
echo " nodock check: dock/clip disabled in Wayland mode (noclip=1 nodock=1)"
|
||||
|
||||
# -- 4g. Phase 17: XWayland started and DISPLAY set ----------------------
|
||||
# -- 4g. Phase 17: XWayland display number allocated (lazy start) --------
|
||||
#
|
||||
# wl_display_open() logs "XWayland started DISPLAY=:<n>" when
|
||||
# wlr_xwayland_create() succeeds; verify the log line is present.
|
||||
# wl_display_open() logs "XWayland DISPLAY=:<n> (lazy: starts on first
|
||||
# X11 client)" when wlr_xwayland_create() succeeds with lazy=true.
|
||||
# The Xwayland process does not start until the first X11 client connects,
|
||||
# avoiding the startup race that caused "Broken pipe" with lazy=false.
|
||||
# (Falls back gracefully if XWayland is unavailable.)
|
||||
if grep -q 'XWayland started DISPLAY=' /tmp/wl-smoke-stderr; then
|
||||
if grep -q 'XWayland DISPLAY=.*lazy' /tmp/wl-smoke-stderr; then
|
||||
XDISP=$(grep -o 'DISPLAY=:[0-9]*' /tmp/wl-smoke-stderr | head -1 | sed 's/DISPLAY=//')
|
||||
echo " xwayland check: XWayland started DISPLAY=$XDISP"
|
||||
echo " xwayland check: XWayland DISPLAY=$XDISP (lazy start)"
|
||||
elif grep -q 'XWayland unavailable' /tmp/wl-smoke-stderr; then
|
||||
echo " xwayland check: XWayland unavailable (skipped)"
|
||||
else
|
||||
|
|
|
|||
Loading…
Reference in New Issue