mirror of
https://github.com/systemd/systemd.git
synced 2025-01-09 01:18:19 +03:00
core: add a new setting DefaultOOMScoreAdjust= and set it to 100 above service manager's by default
Let's make our service managers slightly less likely to be killed by the OOM killer by adjusting our services' OOM score adjustment to 100 above ours. Do this conservatively, i.e. only for regular user sessions.
This commit is contained in:
parent
bb2d1d8ea4
commit
d4a402e4f6
@ -493,6 +493,8 @@ node /org/freedesktop/systemd1 {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s DefaultOOMPolicy = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly i DefaultOOMScoreAdjust = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s CtrlAltDelBurstAction = '...';
|
||||
};
|
||||
interface org.freedesktop.DBus.Peer { ... };
|
||||
@ -735,6 +737,8 @@ node /org/freedesktop/systemd1 {
|
||||
|
||||
<!--property DefaultOOMPolicy is not documented!-->
|
||||
|
||||
<!--property DefaultOOMScoreAdjust is not documented!-->
|
||||
|
||||
<!--property CtrlAltDelBurstAction is not documented!-->
|
||||
|
||||
<!--Autogenerated cross-references for systemd.directives, do not edit-->
|
||||
@ -1131,6 +1135,8 @@ node /org/freedesktop/systemd1 {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="DefaultOOMPolicy"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="DefaultOOMScoreAdjust"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="CtrlAltDelBurstAction"/>
|
||||
|
||||
<!--End of Autogenerated section-->
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "os-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "selinux-access.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
@ -358,6 +359,34 @@ static int property_set_kexec_watchdog(
|
||||
return property_set_watchdog(userdata, WATCHDOG_KEXEC, value);
|
||||
}
|
||||
|
||||
static int property_get_oom_score_adjust(
|
||||
sd_bus *bus,
|
||||
const char *path,
|
||||
const char *interface,
|
||||
const char *property,
|
||||
sd_bus_message *reply,
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Manager *m = userdata;
|
||||
int r, n;
|
||||
|
||||
assert(m);
|
||||
assert(bus);
|
||||
assert(reply);
|
||||
|
||||
if (m->default_oom_score_adjust_set)
|
||||
n = m->default_oom_score_adjust;
|
||||
else {
|
||||
n = 0;
|
||||
r = get_oom_score_adjust(&n);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read current OOM score adjustment value, ignoring: %m");
|
||||
}
|
||||
|
||||
return sd_bus_message_append(reply, "i", n);
|
||||
}
|
||||
|
||||
static int bus_get_unit_by_name(Manager *m, sd_bus_message *message, const char *name, Unit **ret_unit, sd_bus_error *error) {
|
||||
Unit *u;
|
||||
int r;
|
||||
@ -2722,6 +2751,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
|
||||
SD_BUS_PROPERTY("DefaultTasksMax", "t", bus_property_get_tasks_max, offsetof(Manager, default_tasks_max), 0),
|
||||
SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("DefaultOOMPolicy", "s", bus_property_get_oom_policy, offsetof(Manager, default_oom_policy), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("DefaultOOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("CtrlAltDelBurstAction", "s", bus_property_get_emergency_action, offsetof(Manager, cad_burst_action), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
|
||||
SD_BUS_METHOD_WITH_NAMES("GetUnit",
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <linux/oom.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/reboot.h>
|
||||
@ -160,6 +161,8 @@ static NUMAPolicy arg_numa_policy;
|
||||
static usec_t arg_clock_usec;
|
||||
static void *arg_random_seed;
|
||||
static size_t arg_random_seed_size;
|
||||
static int arg_default_oom_score_adjust;
|
||||
static bool arg_default_oom_score_adjust_set;
|
||||
|
||||
/* A copy of the original environment block */
|
||||
static char **saved_env = NULL;
|
||||
@ -633,6 +636,37 @@ static int config_parse_default_timeout_abort(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config_parse_oom_score_adjust(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
int oa, r;
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
arg_default_oom_score_adjust_set = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = parse_oom_score_adjust(rvalue, &oa);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse the OOM score adjust value '%s', ignoring: %m", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
arg_default_oom_score_adjust = oa;
|
||||
arg_default_oom_score_adjust_set = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_config_file(void) {
|
||||
const ConfigTableItem items[] = {
|
||||
{ "Manager", "LogLevel", config_parse_level2, 0, NULL },
|
||||
@ -667,7 +701,7 @@ static int parse_config_file(void) {
|
||||
{ "Manager", "DefaultStandardError", config_parse_output_restricted, 0, &arg_default_std_error },
|
||||
{ "Manager", "DefaultTimeoutStartSec", config_parse_sec, 0, &arg_default_timeout_start_usec },
|
||||
{ "Manager", "DefaultTimeoutStopSec", config_parse_sec, 0, &arg_default_timeout_stop_usec },
|
||||
{ "Manager", "DefaultTimeoutAbortSec", config_parse_default_timeout_abort, 0, NULL },
|
||||
{ "Manager", "DefaultTimeoutAbortSec", config_parse_default_timeout_abort, 0, NULL },
|
||||
{ "Manager", "DefaultRestartSec", config_parse_sec, 0, &arg_default_restart_usec },
|
||||
{ "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval }, /* obsolete alias */
|
||||
{ "Manager", "DefaultStartLimitIntervalSec", config_parse_sec, 0, &arg_default_start_limit_interval },
|
||||
@ -699,6 +733,7 @@ static int parse_config_file(void) {
|
||||
{ "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_default_tasks_max },
|
||||
{ "Manager", "CtrlAltDelBurstAction", config_parse_emergency_action, 0, &arg_cad_burst_action },
|
||||
{ "Manager", "DefaultOOMPolicy", config_parse_oom_policy, 0, &arg_default_oom_policy },
|
||||
{ "Manager", "DefaultOOMScoreAdjust", config_parse_oom_score_adjust, 0, NULL },
|
||||
{}
|
||||
};
|
||||
|
||||
@ -769,6 +804,8 @@ static void set_manager_defaults(Manager *m) {
|
||||
m->default_tasks_accounting = arg_default_tasks_accounting;
|
||||
m->default_tasks_max = arg_default_tasks_max;
|
||||
m->default_oom_policy = arg_default_oom_policy;
|
||||
m->default_oom_score_adjust_set = arg_default_oom_score_adjust_set;
|
||||
m->default_oom_score_adjust = arg_default_oom_score_adjust;
|
||||
|
||||
(void) manager_set_default_rlimits(m, arg_default_rlimit);
|
||||
|
||||
@ -2426,6 +2463,35 @@ static void reset_arguments(void) {
|
||||
arg_random_seed = mfree(arg_random_seed);
|
||||
arg_random_seed_size = 0;
|
||||
arg_clock_usec = 0;
|
||||
|
||||
arg_default_oom_score_adjust_set = false;
|
||||
}
|
||||
|
||||
static void determine_default_oom_score_adjust(void) {
|
||||
int r, a, b;
|
||||
|
||||
/* Run our services at slightly higher OOM score than ourselves. But let's be conservative here, and
|
||||
* do this only if we don't run as root (i.e. only if we are run in user mode, for an unprivileged
|
||||
* user). */
|
||||
|
||||
if (arg_default_oom_score_adjust_set)
|
||||
return;
|
||||
|
||||
if (getuid() == 0)
|
||||
return;
|
||||
|
||||
r = get_oom_score_adjust(&a);
|
||||
if (r < 0)
|
||||
return (void) log_warning_errno(r, "Failed to determine current OOM score adjustment value, ignoring: %m");
|
||||
|
||||
assert_cc(100 <= OOM_SCORE_ADJ_MAX);
|
||||
b = a >= OOM_SCORE_ADJ_MAX - 100 ? OOM_SCORE_ADJ_MAX : a + 100;
|
||||
|
||||
if (a == b)
|
||||
return;
|
||||
|
||||
arg_default_oom_score_adjust = b;
|
||||
arg_default_oom_score_adjust_set = true;
|
||||
}
|
||||
|
||||
static int parse_configuration(const struct rlimit *saved_rlimit_nofile,
|
||||
@ -2459,6 +2525,9 @@ static int parse_configuration(const struct rlimit *saved_rlimit_nofile,
|
||||
if (arg_show_status == _SHOW_STATUS_INVALID)
|
||||
arg_show_status = SHOW_STATUS_YES;
|
||||
|
||||
/* Slightly raise the OOM score for our services if we are running for unprivileged users. */
|
||||
determine_default_oom_score_adjust();
|
||||
|
||||
/* Push variables into the manager environment block */
|
||||
setenv_manager_environment();
|
||||
|
||||
|
@ -370,6 +370,8 @@ struct Manager {
|
||||
usec_t default_timer_accuracy_usec;
|
||||
|
||||
OOMPolicy default_oom_policy;
|
||||
int default_oom_score_adjust;
|
||||
bool default_oom_score_adjust_set;
|
||||
|
||||
int original_log_level;
|
||||
LogTarget original_log_target;
|
||||
|
@ -187,6 +187,11 @@ static void unit_init(Unit *u) {
|
||||
if (ec) {
|
||||
exec_context_init(ec);
|
||||
|
||||
if (u->manager->default_oom_score_adjust_set) {
|
||||
ec->oom_score_adjust = u->manager->default_oom_score_adjust;
|
||||
ec->oom_score_adjust_set = true;
|
||||
}
|
||||
|
||||
if (MANAGER_IS_SYSTEM(u->manager))
|
||||
ec->keyring_mode = EXEC_KEYRING_SHARED;
|
||||
else {
|
||||
|
Loading…
Reference in New Issue
Block a user