diff --git a/include/sway/server.h b/include/sway/server.h index 88dda0975..f99bbda67 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -137,6 +137,8 @@ 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 handle_compositor_new_surface(struct wl_listener *listener, void *data); 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 fce337d51..b35065c12 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c @@ -7,6 +7,7 @@ #include #include "sway/commands.h" #include "sway/config.h" +#include "sway/server.h" #include "sway/tree/container.h" #include "sway/tree/root.h" #include "sway/tree/workspace.h" @@ -53,6 +54,7 @@ struct cmd_results *cmd_exec_process(int argc, char **argv) { // Fork process if ((pid = fork()) == 0) { // Fork child process again + restore_nofile_limit(); setsid(); sigset_t set; sigemptyset(&set); diff --git a/sway/config/bar.c b/sway/config/bar.c index e09add441..d1b342e69 100644 --- a/sway/config/bar.c +++ b/sway/config/bar.c @@ -219,6 +219,8 @@ static void invoke_swaybar(struct bar_config *bar) { sigprocmask(SIG_SETMASK, &set, NULL); signal(SIGPIPE, SIG_DFL); + restore_nofile_limit(); + pid = fork(); if (pid < 0) { sway_log_errno(SWAY_ERROR, "fork failed"); diff --git a/sway/config/output.c b/sway/config/output.c index 8e937b284..6d39c2f55 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -750,6 +750,8 @@ static bool _spawn_swaybg(char **command) { sway_log_errno(SWAY_ERROR, "fork failed"); return false; } else if (pid == 0) { + restore_nofile_limit(); + pid = fork(); if (pid < 0) { sway_log_errno(SWAY_ERROR, "fork failed"); diff --git a/sway/main.c b/sway/main.c index 264fa8473..2c760524f 100644 --- a/sway/main.c +++ b/sway/main.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,7 @@ static bool terminate_request = false; static int exit_value = 0; +static struct rlimit original_nofile_rlimit = {0}; struct sway_server server = {0}; struct sway_debug debug = {0}; @@ -169,6 +171,33 @@ static bool drop_permissions(void) { return true; } +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: " + "getrlimit(NOFILE) failed"); + return; + } + + struct rlimit new_rlimit = original_nofile_rlimit; + new_rlimit.rlim_cur = new_rlimit.rlim_max; + if (setrlimit(RLIMIT_NOFILE, &new_rlimit) != 0) { + sway_log_errno(SWAY_ERROR, "Failed to bump max open files limit: " + "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"); + } +} + void enable_debug_flag(const char *flag) { if (strcmp(flag, "damage=highlight") == 0) { debug.damage = DAMAGE_HIGHLIGHT; @@ -349,6 +378,8 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } + increase_nofile_limit(); + // handle SIGTERM signals signal(SIGTERM, sig_handler); signal(SIGINT, sig_handler); diff --git a/sway/swaynag.c b/sway/swaynag.c index ba582989b..4a0a6d305 100644 --- a/sway/swaynag.c +++ b/sway/swaynag.c @@ -64,6 +64,8 @@ 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(); + pid = fork(); if (pid < 0) { sway_log_errno(SWAY_ERROR, "fork failed");