diff --git a/include/sway/server.h b/include/sway/server.h index 66f0967ce..e7d7094f1 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -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); diff --git a/meson.build b/meson.build index 2d406dec0..9e8e798e1 100644 --- a/meson.build +++ b/meson.build @@ -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() diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index 8f02bbdc7..a966696c5 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c @@ -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) { diff --git a/sway/config/bar.c b/sway/config/bar.c index 6cace0da2..f4efb276c 100644 --- a/sway/config/bar.c +++ b/sway/config/bar.c @@ -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); } diff --git a/sway/config/output.c b/sway/config/output.c index b8a613cc5..5ed518bf4 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -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); } diff --git a/sway/main.c b/sway/main.c index bebb5e1b5..56f09b7e7 100644 --- a/sway/main.c +++ b/sway/main.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -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) { diff --git a/sway/swaynag.c b/sway/swaynag.c index f0a31218a..204a5791a 100644 --- a/sway/swaynag.c +++ b/sway/swaynag.c @@ -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]); } } -