From bfa715a99e51f03f5125459b5ae625d80b34e0e2 Mon Sep 17 00:00:00 2001 From: lkn Date: Sat, 6 Jun 2026 11:14:08 +0200 Subject: [PATCH] fix: unlink wayland socket manually instead of calling wl_display_destroy (wlroots 0.19 multi-backend aborts on display destroy during shutdown) --- src/backend/wayland/wl_backend.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 0118624..ae6fd65 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -879,17 +879,21 @@ wl_display_close(void) wl_state.cursor = NULL; } - /* Tear down the Wayland display so the compositor socket is removed. - * Without this, restart (execvp) fails because the new instance finds - * a stale socket at $XDG_RUNTIME_DIR/wayland-N and refuses to start. - * - * The XWayland server was SIGKILL'd above and server->client was - * NULL'd to prevent wlr_xwayland_server_destroy from double-freeing - * the wl_client during display destroy signal dispatch. - * - * All remaining listeners were removed in the WL_LISTENER_REMOVE block - * above, so no dangling signal handlers remain. */ - wl_display_destroy(wl_state.display); + /* Clean up the Wayland socket so a new compositor instance can bind. + * wl_display_destroy() would do this, but in wlroots 0.19 it aborts + * because the multi-backend's display-destroy handler iterates freed + * child backend pointers. Since execvp replaces the entire process + * image, all memory and fd resources are reclaimed by the kernel. + * The socket file on disk is the only persistent resource we need + * to remove ourselves. */ + if (wl_state.socket_name[0]) { + const char *rt = getenv("XDG_RUNTIME_DIR"); + if (rt) { + char path[256]; + snprintf(path, sizeof(path), "%s/%s", rt, wl_state.socket_name); + unlink(path); + } + } unsetenv("WAYLAND_DISPLAY"); wl_state.renderer = NULL; wl_state.backend = NULL;