summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dopt.c11
-rw-r--r--src/dopt.h4
-rw-r--r--src/prefork.c11
-rw-r--r--src/setuid.c9
4 files changed, 35 insertions, 0 deletions
diff --git a/src/dopt.c b/src/dopt.c
index d680ad5..1e92071 100644
--- a/src/dopt.c
+++ b/src/dopt.c
@@ -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"
diff --git a/src/dopt.h b/src/dopt.h
index 70db3ca..139167b 100644
--- a/src/dopt.h
+++ b/src/dopt.h
@@ -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");