From fbd84aca4a2cbaa4e7daaa9d1a546d2248be8fec Mon Sep 17 00:00:00 2001 From: "Devin J. Pohly" Date: Mon, 3 Jul 2023 14:51:09 -0500 Subject: [PATCH] Unify signal handling under wl_event_loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge our signal handlers into a single function and let Wayland deal with all the struct sigaction stuff. ΔSLOC: -3 --- dwl.c | 83 +++++++++++++++++++++++++---------------------------------- 1 file changed, 35 insertions(+), 48 deletions(-) diff --git a/dwl.c b/dwl.c index 5a1b1b5..b5e146d 100644 --- a/dwl.c +++ b/dwl.c @@ -260,6 +260,7 @@ static void focusmon(const Arg *arg); static void focusstack(const Arg *arg); static Client *focustop(Monitor *m); static void fullscreennotify(struct wl_listener *listener, void *data); +static int handlesig(int signo, void *data); static void incnmaster(const Arg *arg); static void inputdevice(struct wl_listener *listener, void *data); static int keybinding(uint32_t mods, xkb_keysym_t sym); @@ -283,7 +284,6 @@ static void pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, uint32_t time); static void printstatus(void); static void quit(const Arg *arg); -static void quitsignal(int signo); static void rendermon(struct wl_listener *listener, void *data); static void requeststartdrag(struct wl_listener *listener, void *data); static void resize(Client *c, struct wlr_box geo, int interact); @@ -297,7 +297,6 @@ static void setmon(Client *c, Monitor *m, uint32_t newtags); static void setpsel(struct wl_listener *listener, void *data); static void setsel(struct wl_listener *listener, void *data); static void setup(void); -static void sigchld(int unused); static void spawn(const Arg *arg); static void startdrag(struct wl_listener *listener, void *data); static void tag(const Arg *arg); @@ -327,6 +326,8 @@ static pid_t child_pid = -1; static int locked; static void *exclusive_focus; static struct wl_display *dpy; +static struct wl_event_loop *eventloop; +static struct wl_event_source *sighandler[4]; static struct wlr_backend *backend; static struct wlr_scene *scene; static struct wlr_scene_tree *layers[NUM_LAYERS]; @@ -652,6 +653,7 @@ checkidleinhibitor(struct wlr_surface *exclude) void cleanup(void) { + int i; #ifdef XWAYLAND wlr_xwayland_destroy(xwayland); #endif @@ -667,6 +669,8 @@ cleanup(void) wlr_cursor_destroy(cursor); wlr_output_layout_destroy(output_layout); wlr_seat_destroy(seat); + for (i = 0; i < LENGTH(sighandler); i++) + wl_event_source_remove(sighandler[i]); wl_display_destroy(dpy); } @@ -820,8 +824,7 @@ createkeyboard(struct wlr_keyboard *keyboard) wlr_seat_set_keyboard(seat, keyboard); - kb->key_repeat_source = wl_event_loop_add_timer( - wl_display_get_event_loop(dpy), keyrepeat, kb); + kb->key_repeat_source = wl_event_loop_add_timer(eventloop, keyrepeat, kb); /* And add the keyboard to our list of keyboards */ wl_list_insert(&keyboards, &kb->link); @@ -1333,6 +1336,28 @@ fullscreennotify(struct wl_listener *listener, void *data) setfullscreen(c, client_wants_fullscreen(c)); } +int +handlesig(int signo, void *data) +{ + if (signo == SIGCHLD) { +#ifdef XWAYLAND + siginfo_t in; + /* wlroots expects to reap the XWayland process itself, so we + * use WNOWAIT to keep the child waitable until we know it's not + * XWayland. + */ + while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid + && (!xwayland || in.si_pid != xwayland->server->pid)) + waitpid(in.si_pid, NULL, 0); +#else + while (waitpid(-1, NULL, WNOHANG) > 0); +#endif + } else if (signo == SIGINT || signo == SIGTERM) { + quit(NULL); + } + return 0; +} + void incnmaster(const Arg *arg) { @@ -1875,12 +1900,6 @@ quit(const Arg *arg) wl_display_terminate(dpy); } -void -quitsignal(int signo) -{ - quit(NULL); -} - void rendermon(struct wl_listener *listener, void *data) { @@ -1944,8 +1963,6 @@ run(char *startup_cmd) { /* Add a Unix socket to the Wayland display. */ const char *socket = wl_display_add_socket_auto(dpy); - struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = SIG_IGN}; - sigemptyset(&sa.sa_mask); if (!socket) die("startup: display_add_socket_auto"); setenv("WAYLAND_DISPLAY", socket, 1); @@ -1973,8 +1990,6 @@ run(char *startup_cmd) close(piperw[1]); close(piperw[0]); } - /* If nobody is reading the status output, don't terminate */ - sigaction(SIGPIPE, &sa, NULL); printstatus(); /* At this point the outputs are initialized, choose initial selmon based on @@ -2127,20 +2142,14 @@ setsel(struct wl_listener *listener, void *data) void setup(void) { - int layer; - - /* Set up signal handlers */ - struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = sigchld}; - sigemptyset(&sa.sa_mask); - sigaction(SIGCHLD, &sa, NULL); - - sa.sa_handler = quitsignal; - sigaction(SIGINT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); + int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE}; /* The Wayland display is managed by libwayland. It handles accepting * clients from the Unix socket, manging Wayland globals, and so on. */ dpy = wl_display_create(); + eventloop = wl_display_get_event_loop(dpy); + for (i = 0; i < LENGTH(sighandler); i++) + sighandler[i] = wl_event_loop_add_signal(eventloop, sig[i], handlesig, NULL); /* The backend is a wlroots feature which abstracts the underlying input and * output hardware. The autocreate option will choose the most suitable @@ -2155,8 +2164,8 @@ setup(void) /* Initialize the scene graph used to lay out windows */ scene = wlr_scene_create(); - for (layer = 0; layer < NUM_LAYERS; layer++) - layers[layer] = wlr_scene_tree_create(&scene->tree); + for (i = 0; i < NUM_LAYERS; i++) + layers[i] = wlr_scene_tree_create(&scene->tree); /* Create a renderer with the default implementation */ if (!(drw = wlr_renderer_autocreate(backend))) @@ -2308,28 +2317,6 @@ setup(void) #endif } -void -sigchld(int unused) -{ -#ifdef XWAYLAND - siginfo_t in; - /* We should be able to remove this function in favor of a simple - * struct sigaction sa = {.sa_handler = SIG_IGN}; - * sigaction(SIGCHLD, &sa, NULL); - * but the Xwayland implementation in wlroots currently prevents us from - * setting our own disposition for SIGCHLD. - */ - /* WNOWAIT leaves the child in a waitable state, in case this is the - * XWayland process - */ - while (!waitid(P_ALL, 0, &in, WEXITED|WNOHANG|WNOWAIT) && in.si_pid - && (!xwayland || in.si_pid != xwayland->server->pid)) - waitpid(in.si_pid, NULL, 0); -#else - while (waitpid(-1, NULL, WNOHANG) > 0); -#endif -} - void spawn(const Arg *arg) {