diff --git a/man/start-stop-daemon.8 b/man/start-stop-daemon.8 index 257cad70..6c96b7f7 100644 --- a/man/start-stop-daemon.8 +++ b/man/start-stop-daemon.8 @@ -130,6 +130,13 @@ Data can be from 0 to 7 inclusive. Modifies the scheduling priority of the daemon. .It Fl -oom-score-adj Ar adj Modifies the OOM score adjustment of the daemon. +.It Fl -scheduler Ar policy +Sets the scheduling policy of the daemon. Possible values are other, fifo and rr +on POSIX systems and, additionally, batch and idle on Linux. If +.Ar policy +is an integer, it is passed directly to sched_setscheduler(2). +.It Fl -scheduler-priority Ar priority +Sets the priority parameter of the scheduling policy of the daemon. See sched(7) for details. .It Fl 1 , -stdout Ar logfile Redirect the standard output of the process to logfile when started with .Fl background . diff --git a/src/rc/start-stop-daemon.c b/src/rc/start-stop-daemon.c index c0f2b80e..db97f3b3 100644 --- a/src/rc/start-stop-daemon.c +++ b/src/rc/start-stop-daemon.c @@ -21,6 +21,11 @@ #define ONE_MS 1000000 +#ifdef __linux__ +/* For extra SCHED_* defines. */ +# define _GNU_SOURCE +#endif + #include #include #include @@ -60,6 +65,8 @@ static struct pam_conv conv = { NULL, NULL}; #include #endif +#include + #include "einfo.h" #include "queue.h" #include "rc.h" @@ -80,6 +87,8 @@ enum { LONGOPT_CAPABILITIES, LONGOPT_OOM_SCORE_ADJ, LONGOPT_NO_NEW_PRIVS, + LONGOPT_SCHEDULER, + LONGOPT_SCHEDULER_PRIO, LONGOPT_SECBITS, }; @@ -120,6 +129,8 @@ const struct option longopts[] = { { "stdout-logger",1, NULL, '3'}, { "stderr-logger",1, NULL, '4'}, { "progress", 0, NULL, 'P'}, + { "scheduler", 1, NULL, LONGOPT_SCHEDULER}, + { "scheduler-priority", 1, NULL, LONGOPT_SCHEDULER_PRIO}, longopts_COMMON }; const char * const longopts_help[] = { @@ -155,6 +166,8 @@ const char * const longopts_help[] = { "Redirect stdout to process", "Redirect stderr to process", "Print dots each second while waiting", + "Set process scheduler", + "Set process scheduler priority", longopts_help_COMMON }; const char *usagestring = NULL; @@ -332,6 +345,8 @@ int main(int argc, char **argv) mode_t numask = 022; char **margv; unsigned int start_wait = 0; + const char *scheduler = NULL; + int sched_prio = -1; #ifdef HAVE_CAP cap_iab_t cap_iab = NULL; unsigned secbits = 0; @@ -594,6 +609,14 @@ int main(int argc, char **argv) stderr_process = optarg; break; + case LONGOPT_SCHEDULER: /* --scheduler "Process scheduler policy" */ + scheduler = optarg; + break; + + case LONGOPT_SCHEDULER_PRIO: /* --scheduler-priority "Process scheduler priority" */ + sscanf(optarg, "%d", &sched_prio); + break; + case_RC_COMMON_GETOPT } @@ -1064,6 +1087,37 @@ int main(int argc, char **argv) for (i = getdtablesize() - 1; i >= 3; --i) close(i); + if (scheduler != NULL) { + int scheduler_index; + struct sched_param sched = {.sched_priority = sched_prio}; + if (strcmp(scheduler, "fifo") == 0) + scheduler_index = SCHED_FIFO; + else if (strcmp(scheduler, "rr") == 0) + scheduler_index = SCHED_RR; + else if (strcmp(scheduler, "other") == 0) + scheduler_index = SCHED_OTHER; +#ifdef SCHED_BATCH + else if (strcmp(scheduler, "batch") == 0) + scheduler_index = SCHED_BATCH; +#endif +#ifdef SCHED_IDLE + else if (strcmp(scheduler, "idle") == 0) + scheduler_index = SCHED_IDLE; +#endif + else if (sscanf(scheduler, "%d", &scheduler_index) != 1) + eerrorx("Unknown scheduler: %s", scheduler); + + if (sched_prio == -1) + sched.sched_priority = sched_get_priority_min(scheduler_index); + + if (sched_setscheduler(mypid, scheduler_index, &sched)) + eerrorx("Failed to set scheduler: %s", strerror(errno)); + } else if (sched_prio != -1) { + const struct sched_param sched = {.sched_priority = sched_prio}; + if (sched_setparam(mypid, &sched)) + eerrorx("Failed to set scheduler parameters: %s", strerror(errno)); + } + setsid(); execvp(exec, argv); #ifdef HAVE_PAM