Skip to content

Commit

Permalink
Add fields for nice, ionice, oom-score-adj
Browse files Browse the repository at this point in the history
  • Loading branch information
q66 committed Oct 20, 2024
1 parent ca8126a commit 3679b5c
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/baseproc-service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,11 @@ 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
#ifdef __linux__
run_params.nice = nice;
run_params.ionice = ionice;
run_params.oom_adj = oom_adj;
#endif
run_child_proc(run_params);
}
else {
Expand Down
73 changes: 73 additions & 0 deletions src/includes/load-service.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <csignal>
#include <cstring>
#include <cstdlib>
#include <climits>

#include <sys/types.h>
#include <sys/time.h>
Expand Down Expand Up @@ -271,6 +272,11 @@ enum class setting_id_t {
CAPABILITIES,
SECURE_BITS,
#endif
#ifdef __linux__
NICE,
IONICE,
OOM_SCORE_ADJ,
#endif
};

struct setting_details {
Expand Down Expand Up @@ -834,6 +840,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() - (v < 0))) {
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 @@ -1379,6 +1409,12 @@ class service_settings_wrapper
secure_bits_t secbits;
#endif

#ifdef __linux__
int nice = INT_MIN;
int ionice = INT_MIN;
int oom_adj = INT_MIN;
#endif

#if USE_UTMPX
char inittab_id[sizeof(utmpx().ut_id)] = {0};
char inittab_line[sizeof(utmpx().ut_line)] = {0};
Expand Down Expand Up @@ -1640,6 +1676,43 @@ void process_service_line(settings_wrapper &settings, const char *name, const ch
break;
}
#endif
#ifdef __linux__
case setting_id_t::NICE:
{
string nice_str = read_setting_value(input_pos, i, end);
settings.nice = (int)parse_snum_param(input_pos, nice_str, name, -20, 19);
break;
}
case setting_id_t::IONICE:
{
string ionice_str = read_setting_value(input_pos, i, end);
if (ionice_str == "none") {
settings.ionice = 0;
}
else if (starts_with(ionice_str, "rt:")) {
auto nval = parse_unum_param(input_pos, ionice_str.substr(3 /* len 'rt:' */), name, 7);
settings.ionice = (1 << 13) | nval;
}
else if (starts_with(ionice_str, "be:")) {
auto nval = parse_unum_param(input_pos, ionice_str.substr(3 /* len 'be:' */), name, 7);
settings.ionice = (2 << 13) | nval;
}
else if (ionice_str == "idle") {
settings.ionice = 3 << 13;
}
else {
throw service_description_exc(name, "invalid value for ionice: " + ionice_str,
name, input_pos);
}
break;
}
case setting_id_t::OOM_SCORE_ADJ:
{
string oom_adj_str = read_setting_value(input_pos, i, end);
settings.oom_adj = (int)parse_snum_param(input_pos, oom_adj_str, name, -1000, 1000);
break;
}
#endif
case setting_id_t::SOCKET_LISTEN:
settings.socket_path = read_setting_value(input_pos, i, end, nullptr);
break;
Expand Down
24 changes: 24 additions & 0 deletions src/includes/proc-service.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ 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 = INT_MIN;
int ionice = INT_MIN;
int oom_adj = INT_MIN;
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 @@ -203,6 +206,12 @@ class base_process_service : public service_record
bool no_new_privs = false;
#endif

#ifdef __linux__
int nice = INT_MIN;
int ionice = INT_MIN;
int oom_adj = INT_MIN;
#endif

#if SUPPORT_CGROUPS
string run_in_cgroup;
#endif
Expand Down Expand Up @@ -486,6 +495,21 @@ class base_process_service : public service_record
}
#endif

#ifdef __linux__
void set_nice(int nice_v) noexcept
{
nice = nice_v;
}
void set_ionice(int ionice_v) noexcept
{
ionice = ionice_v;
}
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
15 changes: 15 additions & 0 deletions src/load-service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,11 @@ service_record * dirload_service_set::load_reload_service(const char *fullname,
#if SUPPORT_CAPABILITIES
rvalps->set_cap(cap_iab, settings.secbits.get());
#endif
#ifdef __linux__
rvalps->set_nice(settings.nice);
rvalps->set_ionice(settings.ionice);
rvalps->set_oom_adj(settings.oom_adj);
#endif
rvalps->set_rlimits(std::move(settings.rlimits));
rvalps->set_restart_interval(settings.restart_interval, settings.max_restarts);
rvalps->set_restart_delay(settings.restart_delay);
Expand Down Expand Up @@ -793,6 +798,11 @@ service_record * dirload_service_set::load_reload_service(const char *fullname,
#if SUPPORT_CAPABILITIES
rvalps->set_cap(cap_iab, settings.secbits.get());
#endif
#ifdef __linux__
rvalps->set_nice(settings.nice);
rvalps->set_ionice(settings.ionice);
rvalps->set_oom_adj(settings.oom_adj);
#endif
rvalps->set_rlimits(std::move(settings.rlimits));
rvalps->set_pid_file(std::move(settings.pid_file));
rvalps->set_restart_interval(settings.restart_interval, settings.max_restarts);
Expand Down Expand Up @@ -835,6 +845,11 @@ service_record * dirload_service_set::load_reload_service(const char *fullname,
#if SUPPORT_CAPABILITIES
rvalps->set_cap(cap_iab, settings.secbits.get());
#endif
#ifdef __linux__
rvalps->set_nice(settings.nice);
rvalps->set_ionice(settings.ionice);
rvalps->set_oom_adj(settings.oom_adj);
#endif
rvalps->set_rlimits(std::move(settings.rlimits));
rvalps->set_stop_timeout(settings.stop_timeout);
rvalps->set_start_timeout(settings.start_timeout);
Expand Down
5 changes: 5 additions & 0 deletions src/proc-service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,11 @@ bool process_service::start_stop_process(const std::vector<const char *> &cmd) n
run_params.secbits = secbits;
run_params.no_new_privs = onstart_flags.no_new_privs;
#endif
#ifdef __linux__
run_params.nice = nice;
run_params.ionice = ionice;
run_params.oom_adj = oom_adj;
#endif
run_child_proc(run_params);
}
else {
Expand Down
35 changes: 35 additions & 0 deletions src/run-child-proc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ void base_process_service::run_child_proc(run_proc_params params) noexcept
const char *working_dir = params.working_dir;
const char *logfile = params.logfile;
bool on_console = params.on_console;
int nice = params.nice;
int ionice = params.ionice;
int oom_adj = params.oom_adj;
int wpipefd = params.wpipefd;
int csfd = params.csfd;
int notify_fd = params.notify_fd;
Expand Down Expand Up @@ -301,6 +304,38 @@ void base_process_service::run_child_proc(run_proc_params params) noexcept
if (setrlimit(limit.resource_id, &setlimits) != 0) goto failure_out;
}

// nice
if (nice != INT_MIN) {
if (setpriority(PRIO_PROCESS, getpid(), nice) != 0) goto failure_out;
// we usually create a new session leader; that makes nice not very
// useful as the Linux kernel will autogroup processes by session id
// except when disabled - so also work around this where enabled
// the r+ is used in order to avoid creating it where already disabled
errno = 0;
FILE *ag = std::fopen("/proc/self/autogroup", "r+");
if (ag) {
std::fprintf(ag, "%d\n", nice);
std::fclose(ag);
}
else if (errno != ENOENT) goto failure_out;
}

// ionice
if (ionice != INT_MIN) {
#ifdef __NR_ioprio_set
if (syscall(__NR_ioprio_set, 1, (int)getpid(), ionice) != 0) goto failure_out;
#endif
}

// oom score adjustment
if (oom_adj != INT_MIN) {
errno = 0;
FILE *adj = std::fopen("/proc/self/oom_score_adj", "w");
if (!adj) goto failure_out;
std::fprintf(adj, "%d\n", oom_adj);
std::fclose(adj);
}

#if SUPPORT_CGROUPS
if (params.run_in_cgroup != nullptr && *params.run_in_cgroup != 0) {
err.stage = exec_stage::ENTER_CGROUP;
Expand Down
6 changes: 6 additions & 0 deletions src/settings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ setting_details all_settings[] = {
{"secure-bits", setting_id_t::SECURE_BITS, false, true, false},
#endif

#ifdef __linux__
{"nice", setting_id_t::NICE, false, true, false},
{"ionice", setting_id_t::IONICE, false, true, false},
{"oom-score-adj", setting_id_t::OOM_SCORE_ADJ, false, true, false},
#endif

{nullptr, setting_id_t::LAST, false, false, false}
};

Expand Down

0 comments on commit 3679b5c

Please sign in to comment.