From 1c6c9d6e6669dd9c8c56881af18ba857fe78891e Mon Sep 17 00:00:00 2001 From: lkn Date: Sat, 6 Jun 2026 11:06:59 +0200 Subject: [PATCH] fix: call wl_display_destroy on close so restart works (stale socket was preventing execvp from re-binding) --- src/backend/wayland/wl_backend.c | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 91eb3ec..72821b8 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -879,27 +879,20 @@ wl_display_close(void) wl_state.cursor = NULL; } - /* Skip wl_display_destroy() and wl_display_destroy_clients(). + /* 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. * - * wl_display_destroy() fires the display's destroy signal which triggers - * wlroots 0.15 internal object teardown. That teardown has a double- - * remove bug in the XWayland path: wlroots registers a listener on the - * Xwayland wl_client's destroy signal; that listener self-removes during - * client destruction, and wlr_xwayland_server_destroy() then tries to - * wl_list_remove() the already-nulled link, corrupting the heap - * (SIGABRT). + * 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. * - * wl_display_destroy_clients() also blocks: wlroots' XWayland client - * destroy handler performs blocking cleanup that can hang if Xwayland - * is in the middle of protocol dispatch. - * - * Both calls are unnecessary here because Exit() calls exit(0) immediately - * after wl_display_close() returns. The kernel reclaims all resources: - * - file descriptors closed → all Wayland clients get POLLHUP - * - memory freed by OS - * - Xwayland already SIGKILL'd in step 1 - * - event sources removed in step 2 - * - all our signal listeners removed in step 3 */ + * All remaining listeners were removed in the WL_LISTENER_REMOVE block + * above, so no dangling signal handlers remain. */ + wlr_backend_destroy(wl_state.backend); + wl_state.backend = NULL; + wl_display_destroy_clients(wl_state.display); + wl_display_destroy(wl_state.display); unsetenv("WAYLAND_DISPLAY"); wl_state.renderer = NULL; wl_state.backend = NULL;