From: Lennart Poettering Date: Thu, 30 Sep 2021 09:21:18 +0000 (+0200) Subject: core: add a new setting DefaultOOMScoreAdjust= and set it to 100 above service manage... X-Git-Tag: v250-rc1~569^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d4a402e4f6935cd7fa9ae8ea01b30944d9fcb3d0;p=thirdparty%2Fsystemd.git 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. --- diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml index dd6f17519d7..bede2226704 100644 --- a/man/org.freedesktop.systemd1.xml +++ b/man/org.freedesktop.systemd1.xml @@ -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 { + + @@ -1131,6 +1135,8 @@ node /org/freedesktop/systemd1 { + + diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 1f2ac8152c2..99b75598b5a 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -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", diff --git a/src/core/main.c b/src/core/main.c index ff7f189370d..059ba6dd493 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -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(); diff --git a/src/core/manager.h b/src/core/manager.h index 67957fdfbee..97c12ce48f1 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -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; diff --git a/src/core/unit.c b/src/core/unit.c index 4fd499a4f1d..304f67dbf11 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -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 {