Use pthread_atfork() to restore signals and NOFILE limit

This ensures these functions are always called (even when a library
such as wlroots or libc perform the fork) and removes the need to
manually call them.
This commit is contained in:
Simon Ser 2025-04-20 21:09:57 +02:00 committed by Kenny Levinsen
parent 86ff19fade
commit 0e19d85d37
7 changed files with 23 additions and 28 deletions

View file

@ -164,9 +164,6 @@ void server_fini(struct sway_server *server);
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);
void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data);

View file

@ -79,7 +79,7 @@ libudev = wlroots_features['libinput_backend'] ? dependency('libudev') : null_de
math = cc.find_library('m')
rt = cc.find_library('rt')
xcb_icccm = wlroots_features['xwayland'] ? dependency('xcb-icccm') : null_dep
threads = dependency('threads') # for pthread_setschedparam
threads = dependency('threads') # for pthread_setschedparam and pthread_atfork
if get_option('sd-bus-provider') == 'auto'
if not get_option('tray').disabled()

View file

@ -51,8 +51,6 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) {
// Fork process
pid_t child = fork();
if (child == 0) {
restore_nofile_limit();
restore_signals();
setsid();
if (ctx) {

View file

@ -213,8 +213,6 @@ static void invoke_swaybar(struct bar_config *bar) {
sway_log(SWAY_ERROR, "Failed to create fork for swaybar");
return;
} else if (pid == 0) {
restore_nofile_limit();
restore_signals();
if (!sway_set_cloexec(sockets[1], false)) {
_exit(EXIT_FAILURE);
}

View file

@ -1060,8 +1060,6 @@ static bool _spawn_swaybg(char **command) {
sway_log_errno(SWAY_ERROR, "fork failed");
return false;
} else if (pid == 0) {
restore_nofile_limit();
restore_signals();
if (!sway_set_cloexec(sockets[1], false)) {
_exit(EXIT_FAILURE);
}

View file

@ -1,5 +1,6 @@
#include <getopt.h>
#include <pango/pangocairo.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
@ -121,6 +122,16 @@ static bool detect_suid(void) {
return true;
}
static void restore_nofile_limit(void) {
if (original_nofile_rlimit.rlim_cur == 0) {
return;
}
if (setrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
sway_log_errno(SWAY_ERROR, "Failed to restore max open files limit: "
"setrlimit(NOFILE) failed");
}
}
static void increase_nofile_limit(void) {
if (getrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
sway_log_errno(SWAY_ERROR, "Failed to bump max open files limit: "
@ -135,17 +146,10 @@ static void increase_nofile_limit(void) {
"setrlimit(NOFILE) failed");
sway_log(SWAY_INFO, "Running with %d max open files",
(int)original_nofile_rlimit.rlim_cur);
}
}
void restore_nofile_limit(void) {
if (original_nofile_rlimit.rlim_cur == 0) {
return;
}
if (setrlimit(RLIMIT_NOFILE, &original_nofile_rlimit) != 0) {
sway_log_errno(SWAY_ERROR, "Failed to restore max open files limit: "
"setrlimit(NOFILE) failed");
}
pthread_atfork(NULL, NULL, restore_nofile_limit);
}
static int term_signal(int signal, void *data) {
@ -153,6 +157,14 @@ static int term_signal(int signal, void *data) {
return 0;
}
static void restore_signals(void) {
sigset_t set;
sigemptyset(&set);
sigprocmask(SIG_SETMASK, &set, NULL);
signal(SIGCHLD, SIG_DFL);
signal(SIGPIPE, SIG_DFL);
}
static void init_signals(void) {
wl_event_loop_add_signal(server.wl_event_loop, SIGTERM, term_signal, NULL);
wl_event_loop_add_signal(server.wl_event_loop, SIGINT, term_signal, NULL);
@ -162,14 +174,8 @@ static void init_signals(void) {
// prevent ipc write errors from crashing sway
signal(SIGPIPE, SIG_IGN);
}
void restore_signals(void) {
sigset_t set;
sigemptyset(&set);
sigprocmask(SIG_SETMASK, &set, NULL);
signal(SIGCHLD, SIG_DFL);
signal(SIGPIPE, SIG_DFL);
pthread_atfork(NULL, NULL, restore_signals);
}
void enable_debug_flag(const char *flag) {

View file

@ -63,7 +63,6 @@ bool swaynag_spawn(const char *swaynag_command,
sway_log(SWAY_ERROR, "Failed to create fork for swaynag");
goto failed;
} else if (pid == 0) {
restore_nofile_limit();
if (!sway_set_cloexec(sockets[1], false)) {
_exit(EXIT_FAILURE);
}
@ -148,4 +147,3 @@ void swaynag_show(struct swaynag_instance *swaynag) {
close(swaynag->fd[1]);
}
}