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"
#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) {

View file

@ -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);

2
seat.c
View file

@ -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

View file

@ -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