diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dopt.c | 11 | ||||
-rw-r--r-- | src/dopt.h | 4 | ||||
-rw-r--r-- | src/prefork.c | 11 | ||||
-rw-r--r-- | src/setuid.c | 9 |
4 files changed, 35 insertions, 0 deletions
@@ -33,6 +33,7 @@ #include <fcntl.h> #include <errno.h> #include <popt.h> +#include <limits.h> #include <sys/socket.h> #include <netinet/in.h> @@ -49,6 +50,10 @@ int opt_niceness = 5; /* default */ +#ifdef HAVE_LINUX +int opt_oom_score_adj = INT_MIN; /* default is not to change */ +#endif + /** * Number of children running jobs on this machine. If zero (recommended), * then dynamically set from the number of CPUs. @@ -154,6 +159,9 @@ const struct poptOption options[] = { { "no-detach", 0, POPT_ARG_NONE, &opt_no_detach, 0, 0, 0 }, { "no-fifo", 0, POPT_ARG_NONE, &opt_no_fifo, 0, 0, 0 }, { "no-fork", 0, POPT_ARG_NONE, &opt_no_fork, 0, 0, 0 }, +#ifdef HAVE_LINUX + { "oom-score-adj",0, POPT_ARG_INT, &opt_oom_score_adj, 0, 0, 0 }, +#endif { "pid-file", 'P', POPT_ARG_STRING, &arg_pid_file, 0, 0, 0 }, { "port", 'p', POPT_ARG_INT, &arg_port, 0, 0, 0 }, #ifdef HAVE_GSSAPI @@ -191,6 +199,9 @@ static void distccd_show_usage(void) #endif " -P, --pid-file FILE save daemon process id to file\n" " -N, --nice LEVEL lower priority, 20=most nice\n" +#ifdef HAVE_LINUX +" --oom-score-adj ADJ set OOM score adjustment, -1000 to 1000\n" +#endif " --user USER if run by root, change to this persona\n" " --jobs, -j LIMIT maximum tasks at any time\n" " --job-lifetime SECONDS maximum lifetime of a compile request\n" @@ -46,6 +46,10 @@ extern int opt_lifetime; extern char *opt_listen_addr; extern int opt_niceness; +#ifdef HAVE_LINUX +extern int opt_oom_score_adj; +#endif + #ifdef HAVE_AVAHI extern int opt_zeroconf; #endif diff --git a/src/prefork.c b/src/prefork.c index d7e1d84..d4d70d5 100644 --- a/src/prefork.c +++ b/src/prefork.c @@ -38,6 +38,7 @@ #include <signal.h> #include <fcntl.h> #include <time.h> +#include <limits.h> #include <sys/stat.h> #include <sys/types.h> @@ -149,6 +150,16 @@ static int dcc_preforked_child(int listen_fd) const time_t child_lifetime = 60 /* seconds */; start = now = time(NULL); +#ifdef HAVE_LINUX + if (opt_oom_score_adj != INT_MIN) { + FILE *f = fopen("/proc/self/oom_score_adj", "w"); + if (!f || fprintf(f, "%d\n", opt_oom_score_adj) < 0) + rs_log_warning("failed to set oom_score_adj: %s", strerror(errno)); + if (f) + fclose(f); + } +#endif + for (ireq = 0; ireq < child_requests || now - start < child_lifetime; ireq++) { int acc_fd; struct dcc_sockaddr_storage cli_addr; diff --git a/src/setuid.c b/src/setuid.c index d664b84..44bc850 100644 --- a/src/setuid.c +++ b/src/setuid.c @@ -139,6 +139,15 @@ int dcc_discard_root(void) return EXIT_SETUID_FAILED; } +#ifdef HAVE_LINUX + /* On Linux changing the effective user or group ID clears the process's + * "dumpable" flag, which makes all files in the /proc/self/ directory + * owned by root and therefore unmodifiable by the process itself. + * Set the flag again here so we can, e.g., change oom_score_adj. */ + if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) + rs_log_warning("failed to restore dumpable process flag: %s", strerror(errno)); +#endif + #ifdef __linux__ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == 0) rs_trace("successfully set no_new_privs"); |