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
This commit is contained in:
Simon Ser 2024-08-28 15:05:03 +02:00
parent 1abf7e5a4b
commit 412c11ea91
4 changed files with 32 additions and 9 deletions

33
cage.c
View file

@ -61,6 +61,24 @@
#include "xwayland.h" #include "xwayland.h"
#endif #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 static int
sigchld_handler(int fd, uint32_t mask, void *data) 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; server->return_app_code = true;
wl_display_terminate(server->wl_display); server_terminate(server);
return 0; return 0;
} }
@ -189,13 +207,13 @@ drop_permissions(void)
static int static int
handle_signal(int signal, void *data) handle_signal(int signal, void *data)
{ {
struct wl_display *display = data; struct cg_server *server = data;
switch (signal) { switch (signal) {
case SIGINT: case SIGINT:
/* Fallthrough */ /* Fallthrough */
case SIGTERM: case SIGTERM:
wl_display_terminate(display); server_terminate(server);
return 0; return 0;
default: default:
return 0; return 0;
@ -288,11 +306,12 @@ main(int argc, char *argv[])
return 1; 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_loop *event_loop = wl_display_get_event_loop(server.wl_display);
struct wl_event_source *sigint_source = struct wl_event_source *sigint_source = wl_event_loop_add_signal(event_loop, SIGINT, handle_signal, &server);
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);
struct wl_event_source *sigterm_source =
wl_event_loop_add_signal(event_loop, SIGTERM, handle_signal, server.wl_display);
server.backend = wlr_backend_autocreate(event_loop, &server.session); server.backend = wlr_backend_autocreate(event_loop, &server.session);
if (!server.backend) { if (!server.backend) {

View file

@ -240,7 +240,7 @@ output_destroy(struct cg_output *output)
free(output); free(output);
if (wl_list_empty(&server->outputs) && was_nested_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)) { } 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); struct cg_output *prev = wl_container_of(server->outputs.next, prev, link);
output_enable(prev); output_enable(prev);

2
seat.c
View file

@ -258,7 +258,7 @@ handle_keybinding(struct cg_server *server, xkb_keysym_t sym)
{ {
#ifdef DEBUG #ifdef DEBUG
if (sym == XKB_KEY_Escape) { if (sym == XKB_KEY_Escape) {
wl_display_terminate(server->wl_display); server_terminate(server);
return true; return true;
} }
#endif #endif

View file

@ -25,6 +25,7 @@ struct cg_server {
struct wlr_renderer *renderer; struct wlr_renderer *renderer;
struct wlr_allocator *allocator; struct wlr_allocator *allocator;
struct wlr_session *session; struct wlr_session *session;
struct wl_listener display_destroy;
struct cg_seat *seat; struct cg_seat *seat;
struct wlr_idle_notifier_v1 *idle; struct wlr_idle_notifier_v1 *idle;
@ -61,6 +62,9 @@ struct cg_server {
bool xdg_decoration; bool xdg_decoration;
bool allow_vt_switch; bool allow_vt_switch;
bool return_app_code; bool return_app_code;
bool terminated;
}; };
void server_terminate(struct cg_server *server);
#endif #endif