Skip to content

Commit

Permalink
Add support for nice, ioprio, oom-score-adj
Browse files Browse the repository at this point in the history
  • Loading branch information
q66 committed Oct 29, 2024
1 parent 184235d commit 04b6af9
Show file tree
Hide file tree
Showing 17 changed files with 302 additions and 5 deletions.
2 changes: 2 additions & 0 deletions build/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ includes/mconfig.h: ../mconfig tools/mconfig-gen.cc version.conf
DEFAULT_STOP_TIMEOUT=$(DEFAULT_STOP_TIMEOUT) \
$(if $(SUPPORT_CGROUPS),SUPPORT_CGROUPS=$(SUPPORT_CGROUPS),) \
$(if $(SUPPORT_CAPABILITIES),SUPPORT_CAPABILITIES=$(SUPPORT_CAPABILITIES),) \
$(if $(SUPPORT_IOPRIO),SUPPORT_IOPRIO=$(SUPPORT_IOPRIO),) \
$(if $(SUPPORT_OOM_ADJ),SUPPORT_OOM_ADJ=$(SUPPORT_OOM_ADJ),) \
$(if $(USE_UTMPX),USE_UTMPX=$(USE_UTMPX),) \
$(if $(USE_INITGROUPS),USE_INITGROUPS=$(USE_INITGROUPS),) > includes/mconfig.h

Expand Down
2 changes: 2 additions & 0 deletions build/mconfig.mesontemplate
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#mesondefine USE_INITGROUPS
#mesondefine SUPPORT_CGROUPS
#mesondefine SUPPORT_CAPABILITIES
#mesondefine SUPPORT_IOPRIO
#mesondefine SUPPORT_OOM_ADJ
#mesondefine DEFAULT_AUTO_RESTART
#mesondefine DEFAULT_START_TIMEOUT
#mesondefine DEFAULT_STOP_TIMEOUT
Expand Down
6 changes: 6 additions & 0 deletions build/tools/mconfig-gen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ int main(int argc, char **argv)
if (vars.find("SUPPORT_CAPABILITIES") != vars.end()) {
cout << "#define SUPPORT_CAPABILITIES " << vars["SUPPORT_CAPABILITIES"] << "\n";
}
if (vars.find("SUPPORT_IOPRIO") != vars.end()) {
cout << "#define SUPPORT_IOPRIO " << vars["SUPPORT_IOPRIO"] << "\n";
}
if (vars.find("SUPPORT_OOM_ADJ") != vars.end()) {
cout << "#define SUPPORT_OOM_ADJ " << vars["SUPPORT_OOM_ADJ"] << "\n";
}
if (vars.find("DEFAULT_AUTO_RESTART") != vars.end()) {
cout << "#define DEFAULT_AUTO_RESTART " << vars["DEFAULT_AUTO_RESTART"] << "\n";
}
Expand Down
2 changes: 2 additions & 0 deletions configs/mconfig.Linux
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ TEST_LDFLAGS=$(TEST_LDFLAGS_BASE) $(TEST_CXXFLAGS)

SUPPORT_CGROUPS=1
SUPPORT_CAPABILITIES=1
SUPPORT_IOPRIO=1
SUPPORT_OOM_ADJ=1


# Service defaults.
Expand Down
2 changes: 2 additions & 0 deletions configs/mconfig.Linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ FEATURE_SETTINGS=$(
echo ""
echo "SUPPORT_CGROUPS=1"
echo "SUPPORT_CAPABILITIES=1"
echo "SUPPORT_IOPRIO=1"
echo "SUPPORT_OOM_ADJ=1"
)

SERVICE_DEFAULTS=$(
Expand Down
12 changes: 12 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ for var in PREFIX \
BUILD_SHUTDOWN \
SUPPORT_CGROUPS \
SUPPORT_CAPABILITIES \
SUPPORT_IOPRIO \
SUPPORT_OOM_ADJ \
USE_UTMPX \
USE_INITGROUPS \
SYSCONTROLSOCKET \
Expand Down Expand Up @@ -242,6 +244,10 @@ for arg in "$@"; do
--disable-cgroups|--enable-cgroups=no) SUPPORT_CGROUPS=0 ;;
--enable-capabilities|--enable-capabilities=yes) SUPPORT_CAPABILITIES=1 ;;
--disable-capabilities|--enable-capabilities=no) SUPPORT_CAPABILITIES=0 ;;
--enable-ioprio|--enable-ioprio=yes) SUPPORT_IOPRIO=1 ;;
--disable-ioprio|--enable-ioprio=no) SUPPORT_IOPRIO=0 ;;
--enable-oom-adj|--enable-oom-adj=yes) SUPPORT_OOM_ADJ=1 ;;
--disable-oom-adj|--enable-oom-adj=no) SUPPORT_OOM_ADJ=0 ;;
--enable-utmpx|--enable-utmpx=yes) USE_UTMPX=1 ;;
--disable-utmpx|--enable-utmpx=no) USE_UTMPX=0 ;;
--enable-initgroups|--enable-initgroups=yes) USE_INITGROUPS=1 ;;
Expand Down Expand Up @@ -282,11 +288,15 @@ if [ "$PLATFORM" = "Linux" ]; then
: "${BUILD_SHUTDOWN:="yes"}"
: "${SUPPORT_CGROUPS:="1"}"
: "${SUPPORT_CAPABILITIES:="1"}"
: "${SUPPORT_IOPRIO:="1"}"
: "${SUPPORT_OOM_ADJ:="1"}"
: "${SYSCONTROLSOCKET:="/run/dinitctl"}"
else
: "${BUILD_SHUTDOWN:="no"}"
: "${SUPPORT_CGROUPS:="0"}"
: "${SUPPORT_CAPABILITIES:="0"}"
: "${SUPPORT_IOPRIO:="0"}"
: "${SUPPORT_OOM_ADJ:="0"}"
: "${SYSCONTROLSOCKET:="/var/run/dinitctl"}"
fi

Expand Down Expand Up @@ -473,6 +483,8 @@ STRIPOPTS=$STRIPOPTS
SUPPORT_CGROUPS=$SUPPORT_CGROUPS
USE_INITGROUPS=$USE_INITGROUPS
SUPPORT_CAPABILITIES=$SUPPORT_CAPABILITIES
SUPPORT_IOPRIO=$SUPPORT_IOPRIO
SUPPORT_OOM_ADJ=$SUPPORT_OOM_ADJ
# Optional settings
SHUTDOWN_PREFIX=${SHUTDOWN_PREFIX:-}
Expand Down
23 changes: 23 additions & 0 deletions doc/manpages/dinit-service.5.m4
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,12 @@ See the \fBRESOURCE LIMITS\fR section.
Note that some operating systems (notably, OpenBSD) do not support this limit; the
setting will be ignored on such systems.
.TP
\fBnice\fR = \fInice-value\fR
Specifies the CPU priority of the process.
When the given value is out of range for the operating system, it will be clamped to
supported range, but no error will be issued.
On Linux, this also sets the autogroup priority, assuming procfs is mounted.
.TP
\fBrun\-in\-cgroup\fR = \fIcgroup-path\fR
Run the service process(es) in the specified cgroup (see \fBcgroups\fR(7)).
The cgroup is specified as a path; if it has a leading slash, the remainder of the path is
Expand Down Expand Up @@ -580,6 +586,23 @@ The append form can be used to add more secure bits, with everything being ORed
at the end and used as an integer.
.IP
This setting is only available if \fBdinit\fR was built with capabilities support.
.TP
\fBioprio\fR = \fIioprio-value\fR
Specifies the I/O priority class and value for the process.
The permitted values are \fInone\fR, \fIidle\fR, \fIrealtime:PRIO\fR, and
\fIbest-effort:PRIO\fR, where \fIPRIO\fR is an integer value no less than 0
and no more than 7.
.IP
This setting is only available if \fBdinit\fR was built with ioprio support.
.TP
\fBoom-score-adj\fR = \fIadj-value\fR
Specifies the OOM killer score adjustment for the service.
The value is an integer no less than -1000 and no more than 1000.
.IP
This setting is only available if \fBdinit\fR was built with OOM score adjustment support.
.IP
This setting requires the proc filesystem to be mounted, and will result in a
service startup failure if that is not the case.
.\"
.SS OPTIONS
.\"
Expand Down
4 changes: 4 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ fuzzer = get_option('fuzzer')
man_pages = get_option('man-pages')
support_cgroups = get_option('support-cgroups')
support_capabilities = get_option('support-capabilities')
support_ioprio = get_option('support-ioprio')
support_oom_adj = get_option('support-oom-adj')
use_utmpx = get_option('use-utmpx')
use_initgroups = get_option('use-initgroups')
default_auto_restart = get_option('default-auto-restart')
Expand Down Expand Up @@ -71,6 +73,8 @@ mconfig_data.set('DEFAULT_STOP_TIMEOUT', default_stop_timeout)
mconfig_data.set10('USE_INITGROUPS', use_initgroups)
mconfig_data.set10('SUPPORT_CGROUPS', support_cgroups.auto() and platform == 'linux' or support_cgroups.enabled())
mconfig_data.set10('SUPPORT_CAPABILITIES', libcap_dep.found() and not support_capabilities.disabled())
mconfig_data.set10('SUPPORT_IOPRIO', support_ioprio.auto() and platform == 'linux' or support_ioprio.enabled())
mconfig_data.set10('SUPPORT_OOM_ADJ', support_oom_adj.auto() and platform == 'linux' or support_oom_adj.enabled())
if use_utmpx.enabled() or (use_utmpx.auto() and compiler.has_header_symbol('utmpx.h', '_PATH_UTMPX') and
compiler.has_header_symbol('utmpx.h', '_PATH_WTMPX'))
mconfig_data.set('USE_UTMPX', '1')
Expand Down
12 changes: 12 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,18 @@ option(
value : 'auto',
description : 'Enable capabilities support.'
)
option(
'support-ioprio',
type : 'feature',
value : 'auto',
description : 'Enable ioprio support.'
)
option(
'support-oom-adj',
type : 'feature',
value : 'auto',
description : 'Enable OOM score adjustment support.'
)
option(
'build-shutdown',
type : 'feature',
Expand Down
7 changes: 7 additions & 0 deletions src/baseproc-service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ bool base_process_service::start_ps_process(const std::vector<const char *> &cmd
run_params.env_file = env_file.c_str();
run_params.output_fd = log_output_fd;
run_params.input_fd = input_fd;
run_params.nice = nice;
#if SUPPORT_CGROUPS
run_params.run_in_cgroup = run_in_cgroup.c_str();
#endif
Expand All @@ -265,6 +266,12 @@ bool base_process_service::start_ps_process(const std::vector<const char *> &cmd
run_params.secbits = secbits;
run_params.no_new_privs = onstart_flags.no_new_privs;
#endif
#if SUPPORT_IOPRIO
run_params.ioprio = ioprio;
#endif
#if SUPPORT_OOM_ADJ
run_params.oom_adj = oom_adj;
#endif
run_child_proc(run_params);
}
else {
Expand Down
95 changes: 94 additions & 1 deletion src/includes/load-service.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ enum class setting_id_t {
LOGFILE_GID, LOG_TYPE, LOG_BUFFER_SIZE, CONSUMER_OF, RESTART, SMOOTH_RECOVERY, OPTIONS,
LOAD_OPTIONS, TERM_SIGNAL, TERMSIGNAL /* deprecated */, RESTART_LIMIT_INTERVAL, RESTART_DELAY,
RESTART_LIMIT_COUNT, STOP_TIMEOUT, START_TIMEOUT, RUN_AS, CHAIN_TO, READY_NOTIFICATION,
INITTAB_ID, INITTAB_LINE,
INITTAB_ID, INITTAB_LINE, NICE,
// Prefixed with SETTING_ to avoid name collision with system macros:
SETTING_RLIMIT_NOFILE, SETTING_RLIMIT_CORE, SETTING_RLIMIT_DATA, SETTING_RLIMIT_ADDRSPACE,
// Possibly unsupported depending on platform/build options:
Expand All @@ -277,6 +277,12 @@ enum class setting_id_t {
CAPABILITIES,
SECURE_BITS,
#endif
#if SUPPORT_IOPRIO
IOPRIO,
#endif
#if SUPPORT_OOM_ADJ
OOM_SCORE_ADJ,
#endif
};

struct setting_details {
Expand Down Expand Up @@ -840,6 +846,30 @@ inline unsigned long long parse_unum_param(file_pos_ref input_pos, const std::st
}
}

// Parse a signed numeric parameter value
inline long long parse_snum_param(file_pos_ref input_pos, const std::string &param,
const std::string &service_name, long long min = std::numeric_limits<long long>::min(),
long long max = std::numeric_limits<long long>::max())
{
const char * num_err_msg = "specified value contains invalid numeric characters or is outside "
"allowed range.";

std::size_t ind = 0;
try {
long long v = std::stoll(param, &ind, 0);
if (v < min || v > max || ind != param.length()) {
throw service_description_exc(service_name, num_err_msg, input_pos);
}
return v;
}
catch (std::out_of_range &exc) {
throw service_description_exc(service_name, num_err_msg, input_pos);
}
catch (std::invalid_argument &exc) {
throw service_description_exc(service_name, num_err_msg, input_pos);
}
}

// In a vector, find or create rlimits for a particular resource type.
inline service_rlimits &find_rlimits(std::vector<service_rlimits> &all_rlimits, int resource_id)
{
Expand Down Expand Up @@ -1373,6 +1403,8 @@ class service_settings_wrapper
gid_t run_as_uid_gid = -1; // primary group of "run as" uid if known
gid_t run_as_gid = -1;

int nice = 0;

string chain_to_name;
string consumer_of_name;

Expand All @@ -1385,6 +1417,14 @@ class service_settings_wrapper
secure_bits_t secbits;
#endif

#if SUPPORT_IOPRIO
int ioprio = -1;
#endif

#if SUPPORT_OOM_ADJ
int oom_adj = 0;
#endif

#if USE_UTMPX
char inittab_id[sizeof(utmpx().ut_id)] = {0};
char inittab_line[sizeof(utmpx().ut_line)] = {0};
Expand Down Expand Up @@ -1467,6 +1507,19 @@ class service_settings_wrapper
if (log_type != log_type_id::NONE) {
report_lint("option 'log_type' was specified, but ignored for the specified (or default) service type.");
}
if (nice != 0) {
report_lint("option 'nice' was specified, but ignored for the specified (or default) service type.");
}
#if SUPPORT_IOPRIO
if (ioprio >= 0) {
report_lint("option 'ioprio' was specified, but ignored for the specified (or default) service type.");
}
#endif
#if SUPPORT_OOM_ADJ
if (oom_adj != 0) {
report_lint("option 'oom-score-adj' was specified, but ignored for the specified (or default) service type.");
}
#endif
}

if (do_report_lint) {
Expand Down Expand Up @@ -1650,6 +1703,46 @@ void process_service_line(settings_wrapper &settings, const char *name, const ch
break;
}
#endif
case setting_id_t::NICE:
{
string nice_str = read_setting_value(input_pos, i, end);
settings.nice = 1 | ((int)parse_snum_param(input_pos, nice_str, name,
std::numeric_limits<int>::min() / 2, std::numeric_limits<int>::max() / 2) << 1);
break;
}
#if SUPPORT_IOPRIO
case setting_id_t::IOPRIO:
{
string ioprio_str = read_setting_value(input_pos, i, end);
if (ioprio_str == "none") {
settings.ioprio = 0;
}
else if (starts_with(ioprio_str, "realtime:")) {
auto nval = parse_unum_param(input_pos, ioprio_str.substr(9 /* len 'realtime:' */), name, 7);
settings.ioprio = (1 << 13) | nval;
}
else if (starts_with(ioprio_str, "best-effort:")) {
auto nval = parse_unum_param(input_pos, ioprio_str.substr(12 /* len 'best-effort:' */), name, 7);
settings.ioprio = (2 << 13) | nval;
}
else if (ioprio_str == "idle") {
settings.ioprio = 3 << 13;
}
else {
throw service_description_exc(name, "invalid value for ioprio: " + ioprio_str,
name, input_pos);
}
break;
}
#endif
#if SUPPORT_OOM_ADJ
case setting_id_t::OOM_SCORE_ADJ:
{
string oom_adj_str = read_setting_value(input_pos, i, end);
settings.oom_adj = 1 | ((int)parse_snum_param(input_pos, oom_adj_str, name, -1000, 1000) << 1);
break;
}
#endif
case setting_id_t::SOCKET_LISTEN:
settings.socket_path = read_setting_value(input_pos, i, end, nullptr);
break;
Expand Down
36 changes: 36 additions & 0 deletions src/includes/proc-service.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ struct run_proc_params
bool on_console; // whether to run on console
bool in_foreground; // if on console: whether to run in foreground
bool unmask_sigint = false; // if in foreground: whether to unmask SIGINT
int nice = 0; // the process nice value
#if SUPPORT_IOPRIO
int ioprio = -1; // scheduling class and priority for the process
#endif
#if SUPPORT_OOM_ADJ
int oom_adj = 0; // oom score adjustment value
#endif
int wpipefd; // pipe to which error status will be sent (if error occurs)
int csfd; // control socket fd (or -1); may be moved
int socket_fd; // pre-opened socket fd (or -1); may be moved
Expand Down Expand Up @@ -232,6 +239,16 @@ class base_process_service : public service_record
unsigned log_buf_size = 0; // log buffer current size
std::vector<char, default_init_allocator<char>> log_buffer;

int nice = 0;

#if SUPPORT_IOPRIO
int ioprio = -1;
#endif

#if SUPPORT_OOM_ADJ
int oom_adj = 0;
#endif

std::vector<service_rlimits> rlimits; // resource limits

#if SUPPORT_CAPABILITIES
Expand Down Expand Up @@ -519,6 +536,25 @@ class base_process_service : public service_record
}
#endif

void set_nice(int nice_v) noexcept
{
nice = nice_v;
}

#if SUPPORT_IOPRIO
void set_ioprio(int ioprio_v) noexcept
{
ioprio = ioprio_v;
}
#endif

#if SUPPORT_OOM_ADJ
void set_oom_adj(int oom_adj_v) noexcept
{
oom_adj = oom_adj_v;
}
#endif

void set_rlimits(std::vector<service_rlimits> &&rlimits_p)
{
rlimits = std::move(rlimits_p);
Expand Down
Loading

0 comments on commit 04b6af9

Please sign in to comment.