From 8238e5242bdbbc4c3b7cba0651c620a89b872a27 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Sun, 9 Mar 2025 12:07:11 +0100 Subject: [PATCH] Use SIG_IGN for SIGCHLD instead of our own handler The behavior of handlers registered with signal(3p) is not well-defined for signals delivered more than once, as laid out in the man page. We should replace our use of signal with sigaction, but for SIGCHLD specifically we can also just skip the signals altogether by setting the handler to SIG_IGN which causes child reaping to not be required. Fixes: https://github.com/swaywm/sway/pull/8567 --- include/sway/server.h | 1 + sway/commands/exec_always.c | 5 +---- sway/config/bar.c | 7 +------ sway/main.c | 19 +++++++++++-------- 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/include/sway/server.h b/include/sway/server.h index 95c9c45b..feb516c5 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -163,6 +163,7 @@ bool server_start(struct sway_server *server); void server_run(struct sway_server *server); void restore_nofile_limit(void); +void restore_signals(void); void handle_new_output(struct wl_listener *listener, void *data); diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index 14566fc4..8f02bbdc 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c @@ -52,11 +52,8 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) { pid_t child = fork(); if (child == 0) { restore_nofile_limit(); + restore_signals(); setsid(); - sigset_t set; - sigemptyset(&set); - sigprocmask(SIG_SETMASK, &set, NULL); - signal(SIGPIPE, SIG_DFL); if (ctx) { const char *token = launcher_ctx_get_token_name(ctx); diff --git a/sway/config/bar.c b/sway/config/bar.c index f7eddfbb..6cace0da 100644 --- a/sway/config/bar.c +++ b/sway/config/bar.c @@ -213,13 +213,8 @@ static void invoke_swaybar(struct bar_config *bar) { sway_log(SWAY_ERROR, "Failed to create fork for swaybar"); return; } else if (pid == 0) { - // Remove the SIGUSR1 handler that wlroots adds for xwayland - sigset_t set; - sigemptyset(&set); - sigprocmask(SIG_SETMASK, &set, NULL); - signal(SIGPIPE, SIG_DFL); - restore_nofile_limit(); + restore_signals(); if (!sway_set_cloexec(sockets[1], false)) { _exit(EXIT_FAILURE); } diff --git a/sway/main.c b/sway/main.c index 0cc7623d..cabdd3aa 100644 --- a/sway/main.c +++ b/sway/main.c @@ -48,13 +48,6 @@ void sig_handler(int signal) { sway_terminate(EXIT_SUCCESS); } -void sigchld_handler(int signal) { - pid_t pid; - do { - pid = waitpid(-1, NULL, WNOHANG); - } while (pid > 0); -} - void run_as_ipc_client(char *command, char *socket_path) { int socketfd = ipc_open_socket(socket_path); uint32_t len = strlen(command); @@ -159,6 +152,14 @@ void restore_nofile_limit(void) { } } +void restore_signals(void) { + sigset_t set; + sigemptyset(&set); + sigprocmask(SIG_SETMASK, &set, NULL); + signal(SIGCHLD, SIG_DFL); + signal(SIGPIPE, SIG_DFL); +} + void enable_debug_flag(const char *flag) { if (strcmp(flag, "noatomic") == 0) { debug.noatomic = true; @@ -332,7 +333,9 @@ int main(int argc, char **argv) { // handle SIGTERM signals signal(SIGTERM, sig_handler); signal(SIGINT, sig_handler); - signal(SIGCHLD, sigchld_handler); + + // avoid need to reap children + signal(SIGCHLD, SIG_IGN); // prevent ipc from crashing sway signal(SIGPIPE, SIG_IGN);