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
This commit is contained in:
Kenny Levinsen 2025-03-09 12:07:11 +01:00
parent 5d7b9a8320
commit 8238e5242b
4 changed files with 14 additions and 18 deletions

View file

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

View file

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

View file

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

View file

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