From 412c11ea91647c30abce3c4a0ec6f6b97b408bf0 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 28 Aug 2024 15:05:03 +0200 Subject: [PATCH] cage: fix abort on shutdown Workaround for [1]: register a listener for wl_display destroy and avoid calling wl_display_terminate() after. [1]: https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/421 --- cage.c | 33 ++++++++++++++++++++++++++------- output.c | 2 +- seat.c | 2 +- server.h | 4 ++++ 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/cage.c b/cage.c index b5ba6c5..26ab9ef 100644 --- a/cage.c +++ b/cage.c @@ -61,6 +61,24 @@ #include "xwayland.h" #endif +void +server_terminate(struct cg_server *server) +{ + // Workaround for https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/421 + if (server->terminated) { + return; + } + + wl_display_terminate(server->wl_display); +} + +static void +handle_display_destroy(struct wl_listener *listener, void *data) +{ + struct cg_server *server = wl_container_of(listener, server, display_destroy); + server->terminated = true; +} + static int sigchld_handler(int fd, uint32_t mask, void *data) { @@ -76,7 +94,7 @@ sigchld_handler(int fd, uint32_t mask, void *data) } server->return_app_code = true; - wl_display_terminate(server->wl_display); + server_terminate(server); return 0; } @@ -189,13 +207,13 @@ drop_permissions(void) static int handle_signal(int signal, void *data) { - struct wl_display *display = data; + struct cg_server *server = data; switch (signal) { case SIGINT: /* Fallthrough */ case SIGTERM: - wl_display_terminate(display); + server_terminate(server); return 0; default: return 0; @@ -288,11 +306,12 @@ main(int argc, char *argv[]) return 1; } + server.display_destroy.notify = handle_display_destroy; + wl_display_add_destroy_listener(server.wl_display, &server.display_destroy); + struct wl_event_loop *event_loop = wl_display_get_event_loop(server.wl_display); - struct wl_event_source *sigint_source = - wl_event_loop_add_signal(event_loop, SIGINT, handle_signal, server.wl_display); - struct wl_event_source *sigterm_source = - wl_event_loop_add_signal(event_loop, SIGTERM, handle_signal, server.wl_display); + struct wl_event_source *sigint_source = wl_event_loop_add_signal(event_loop, SIGINT, handle_signal, &server); + struct wl_event_source *sigterm_source = wl_event_loop_add_signal(event_loop, SIGTERM, handle_signal, &server); server.backend = wlr_backend_autocreate(event_loop, &server.session); if (!server.backend) { diff --git a/output.c b/output.c index 6eb2472..f1c0419 100644 --- a/output.c +++ b/output.c @@ -240,7 +240,7 @@ output_destroy(struct cg_output *output) free(output); if (wl_list_empty(&server->outputs) && was_nested_output) { - wl_display_terminate(server->wl_display); + server_terminate(server); } else if (server->output_mode == CAGE_MULTI_OUTPUT_MODE_LAST && !wl_list_empty(&server->outputs)) { struct cg_output *prev = wl_container_of(server->outputs.next, prev, link); output_enable(prev); diff --git a/seat.c b/seat.c index 4e287d9..cdf8798 100644 --- a/seat.c +++ b/seat.c @@ -258,7 +258,7 @@ handle_keybinding(struct cg_server *server, xkb_keysym_t sym) { #ifdef DEBUG if (sym == XKB_KEY_Escape) { - wl_display_terminate(server->wl_display); + server_terminate(server); return true; } #endif diff --git a/server.h b/server.h index 8759ed5..f7d70d7 100644 --- a/server.h +++ b/server.h @@ -25,6 +25,7 @@ struct cg_server { struct wlr_renderer *renderer; struct wlr_allocator *allocator; struct wlr_session *session; + struct wl_listener display_destroy; struct cg_seat *seat; struct wlr_idle_notifier_v1 *idle; @@ -61,6 +62,9 @@ struct cg_server { bool xdg_decoration; bool allow_vt_switch; bool return_app_code; + bool terminated; }; +void server_terminate(struct cg_server *server); + #endif