diff --git a/doc/configuration.txt b/doc/configuration.txt index 68777b2b8c..845a2eb120 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -1524,6 +1524,8 @@ The following keywords are supported in the "global" section : - tune.quic.retry-threshold - tune.quic.socket-owner - tune.quic.zero-copy-fwd-send + - tune.renice.runtime + - tune.renice.startup - tune.rcvbuf.backend - tune.rcvbuf.client - tune.rcvbuf.frontend @@ -4060,6 +4062,24 @@ tune.quic.zero-copy-fwd-send { on | off } See also: tune.disable-zero-copy-forwarding +tune.renice.runtime + This configuration option takes a value between -20 and 19. It applies a + scheduling priority as documented in man 2 setpriority. This priority is + applied after the configuration parsing, which means only the worker or the + standalone process will apply it. It is usually configured to set a higher + priority than a process doing configuration parsing (tune.renice.startup). + + See also: tune.renice.startup + +tune.renice.startup + This configuration option takes a value between -20 and 19. It applies a + scheduling priority as documented in man 2 setpriority. This priority is + applied before applying the rest of the configuration which can be useful if + you want to lower the priority for configuration parsing. In master-worker + mode, this priority is kept by the master after configuration parsing. + + See also: tune.renice.runtime + tune.rcvbuf.backend tune.rcvbuf.frontend For the kernel socket receive buffer size on non-connected sockets to this diff --git a/include/haproxy/global-t.h b/include/haproxy/global-t.h index dda39705db..4e41860ef1 100644 --- a/include/haproxy/global-t.h +++ b/include/haproxy/global-t.h @@ -190,6 +190,8 @@ struct global { int pool_low_count; /* max number of opened fd before we stop using new idle connections */ int pool_high_count; /* max number of opened fd before we start killing idle connections when creating new connections */ size_t pool_cache_size; /* per-thread cache size per pool (defaults to CONFIG_HAP_POOL_CACHE_SIZE) */ + int renice_startup; /* startup nice()+100 value during startup; 0 = unset */ + int renice_runtime; /* startup nice()+100 value during runtime; 0 = unset */ unsigned short idle_timer; /* how long before an empty buffer is considered idle (ms) */ unsigned short no_zero_copy_fwd; /* Flags to disable zero-copy fast-forwarding (global & per-protocols) */ int nb_stk_ctr; /* number of stick counters, defaults to MAX_SESS_STKCTR */ diff --git a/src/cfgparse-global.c b/src/cfgparse-global.c index daca46ac84..d52fa90c05 100644 --- a/src/cfgparse-global.c +++ b/src/cfgparse-global.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -1540,6 +1541,55 @@ static int cfg_parse_global_parser_pause(char **args, int section_type, return 0; } +/* config parser for global "tune.renice.startup" and "tune.renice.runtime", + * accepts -20 to +19 inclusive, stored as 80..119. + */ +static int cfg_parse_tune_renice(char **args, int section_type, struct proxy *curpx, + const struct proxy *defpx, const char *file, int line, + char **err) +{ + int prio; + char *stop; + + if (too_many_args(1, args, err, NULL)) + return -1; + + prio = strtol(args[1], &stop, 10); + if ((*stop != '\0') || (prio < -20 || prio > 19)) { + memprintf(err, "'%s' only supports values between -20 and 19 inclusive (was given %d)", args[0], prio); + return -1; + } + + /* 'runtime' vs 'startup' */ + if (args[0][12] == 'r') { + global.tune.renice_runtime = prio + 100; + } else if (args[0][12] == 's') { + /* 'startup' executes only in discovery mode */ + + global.tune.renice_startup = prio + 100; + if (setpriority(PRIO_PROCESS, 0, prio) == -1) + ha_warning("couldn't set the runtime nice value to %d: %s\n", prio, strerror(errno)); + } else { + BUG_ON(1, "Triggered in cfg_parse_tune_renice() by unsupported keyword.\n"); + } + + return 0; +} +/* config parser for global "tune.renice.startup" and "tune.renice.runtime", + * accepts -20 to +19 inclusive, stored as 80..119. + */ +static int cfg_parse_tune_renice_startup(char **args, int section_type, struct proxy *curpx, + const struct proxy *defpx, const char *file, int line, + char **err) +{ + /* 'startup' executes only in discovery mode */ + if (!(global.mode & MODE_DISCOVERY)) + return 0; + + return cfg_parse_tune_renice(args, section_type, curpx, defpx, file, line, err); +} + + static struct cfg_kw_list cfg_kws = {ILH, { { CFG_GLOBAL, "prealloc-fd", cfg_parse_prealloc_fd }, { CFG_GLOBAL, "force-cfg-parser-pause", cfg_parse_global_parser_pause, KWF_EXPERIMENTAL }, @@ -1563,6 +1613,8 @@ static struct cfg_kw_list cfg_kws = {ILH, { { CFG_GLOBAL, "tune.bufsize", cfg_parse_global_tune_opts }, { CFG_GLOBAL, "tune.maxrewrite", cfg_parse_global_tune_opts }, { CFG_GLOBAL, "tune.idletimer", cfg_parse_global_tune_opts }, + { CFG_GLOBAL, "tune.renice.startup", cfg_parse_tune_renice_startup, KWF_DISCOVERY }, + { CFG_GLOBAL, "tune.renice.runtime", cfg_parse_tune_renice, 0 }, { CFG_GLOBAL, "tune.rcvbuf.client", cfg_parse_global_tune_opts }, { CFG_GLOBAL, "tune.rcvbuf.server", cfg_parse_global_tune_opts }, { CFG_GLOBAL, "tune.sndbuf.client", cfg_parse_global_tune_opts }, diff --git a/src/haproxy.c b/src/haproxy.c index 80bb090b36..e557958632 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -3942,6 +3942,15 @@ int main(int argc, char **argv) } } + /* applies the renice value in the worker or standalone after configuration parsing + * but before chaning identity */ + if (!master && global.tune.renice_runtime) { + if (setpriority(PRIO_PROCESS, 0, global.tune.renice_runtime - 100) == -1) { + ha_warning("[%s.main()] couldn't set the runtime nice value to %d: %s\n", + argv[0], global.tune.renice_runtime - 100, strerror(errno)); + } + } + /* Must chroot and setgid/setuid in the children */ /* chroot if needed */ if (global.chroot != NULL) {