Skip to content

Commit d4a402e

Browse files
committed
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.
1 parent bb2d1d8 commit d4a402e

File tree

5 files changed

+113
-1
lines changed

5 files changed

+113
-1
lines changed

man/org.freedesktop.systemd1.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,8 @@ node /org/freedesktop/systemd1 {
493493
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
494494
readonly s DefaultOOMPolicy = '...';
495495
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
496+
readonly i DefaultOOMScoreAdjust = ...;
497+
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
496498
readonly s CtrlAltDelBurstAction = '...';
497499
};
498500
interface org.freedesktop.DBus.Peer { ... };
@@ -735,6 +737,8 @@ node /org/freedesktop/systemd1 {
735737

736738
<!--property DefaultOOMPolicy is not documented!-->
737739

740+
<!--property DefaultOOMScoreAdjust is not documented!-->
741+
738742
<!--property CtrlAltDelBurstAction is not documented!-->
739743

740744
<!--Autogenerated cross-references for systemd.directives, do not edit-->
@@ -1131,6 +1135,8 @@ node /org/freedesktop/systemd1 {
11311135

11321136
<variablelist class="dbus-property" generated="True" extra-ref="DefaultOOMPolicy"/>
11331137

1138+
<variablelist class="dbus-property" generated="True" extra-ref="DefaultOOMScoreAdjust"/>
1139+
11341140
<variablelist class="dbus-property" generated="True" extra-ref="CtrlAltDelBurstAction"/>
11351141

11361142
<!--End of Autogenerated section-->

src/core/dbus-manager.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "os-util.h"
3232
#include "parse-util.h"
3333
#include "path-util.h"
34+
#include "process-util.h"
3435
#include "selinux-access.h"
3536
#include "stat-util.h"
3637
#include "string-util.h"
@@ -358,6 +359,34 @@ static int property_set_kexec_watchdog(
358359
return property_set_watchdog(userdata, WATCHDOG_KEXEC, value);
359360
}
360361

362+
static int property_get_oom_score_adjust(
363+
sd_bus *bus,
364+
const char *path,
365+
const char *interface,
366+
const char *property,
367+
sd_bus_message *reply,
368+
void *userdata,
369+
sd_bus_error *error) {
370+
371+
Manager *m = userdata;
372+
int r, n;
373+
374+
assert(m);
375+
assert(bus);
376+
assert(reply);
377+
378+
if (m->default_oom_score_adjust_set)
379+
n = m->default_oom_score_adjust;
380+
else {
381+
n = 0;
382+
r = get_oom_score_adjust(&n);
383+
if (r < 0)
384+
log_debug_errno(r, "Failed to read current OOM score adjustment value, ignoring: %m");
385+
}
386+
387+
return sd_bus_message_append(reply, "i", n);
388+
}
389+
361390
static int bus_get_unit_by_name(Manager *m, sd_bus_message *message, const char *name, Unit **ret_unit, sd_bus_error *error) {
362391
Unit *u;
363392
int r;
@@ -2722,6 +2751,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
27222751
SD_BUS_PROPERTY("DefaultTasksMax", "t", bus_property_get_tasks_max, offsetof(Manager, default_tasks_max), 0),
27232752
SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
27242753
SD_BUS_PROPERTY("DefaultOOMPolicy", "s", bus_property_get_oom_policy, offsetof(Manager, default_oom_policy), SD_BUS_VTABLE_PROPERTY_CONST),
2754+
SD_BUS_PROPERTY("DefaultOOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
27252755
SD_BUS_PROPERTY("CtrlAltDelBurstAction", "s", bus_property_get_emergency_action, offsetof(Manager, cad_burst_action), SD_BUS_VTABLE_PROPERTY_CONST),
27262756

27272757
SD_BUS_METHOD_WITH_NAMES("GetUnit",

src/core/main.c

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <errno.h>
44
#include <fcntl.h>
55
#include <getopt.h>
6+
#include <linux/oom.h>
67
#include <sys/mount.h>
78
#include <sys/prctl.h>
89
#include <sys/reboot.h>
@@ -160,6 +161,8 @@ static NUMAPolicy arg_numa_policy;
160161
static usec_t arg_clock_usec;
161162
static void *arg_random_seed;
162163
static size_t arg_random_seed_size;
164+
static int arg_default_oom_score_adjust;
165+
static bool arg_default_oom_score_adjust_set;
163166

164167
/* A copy of the original environment block */
165168
static char **saved_env = NULL;
@@ -633,6 +636,37 @@ static int config_parse_default_timeout_abort(
633636
return 0;
634637
}
635638

639+
static int config_parse_oom_score_adjust(
640+
const char *unit,
641+
const char *filename,
642+
unsigned line,
643+
const char *section,
644+
unsigned section_line,
645+
const char *lvalue,
646+
int ltype,
647+
const char *rvalue,
648+
void *data,
649+
void *userdata) {
650+
651+
int oa, r;
652+
653+
if (isempty(rvalue)) {
654+
arg_default_oom_score_adjust_set = false;
655+
return 0;
656+
}
657+
658+
r = parse_oom_score_adjust(rvalue, &oa);
659+
if (r < 0) {
660+
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse the OOM score adjust value '%s', ignoring: %m", rvalue);
661+
return 0;
662+
}
663+
664+
arg_default_oom_score_adjust = oa;
665+
arg_default_oom_score_adjust_set = true;
666+
667+
return 0;
668+
}
669+
636670
static int parse_config_file(void) {
637671
const ConfigTableItem items[] = {
638672
{ "Manager", "LogLevel", config_parse_level2, 0, NULL },
@@ -667,7 +701,7 @@ static int parse_config_file(void) {
667701
{ "Manager", "DefaultStandardError", config_parse_output_restricted, 0, &arg_default_std_error },
668702
{ "Manager", "DefaultTimeoutStartSec", config_parse_sec, 0, &arg_default_timeout_start_usec },
669703
{ "Manager", "DefaultTimeoutStopSec", config_parse_sec, 0, &arg_default_timeout_stop_usec },
670-
{ "Manager", "DefaultTimeoutAbortSec", config_parse_default_timeout_abort, 0, NULL },
704+
{ "Manager", "DefaultTimeoutAbortSec", config_parse_default_timeout_abort, 0, NULL },
671705
{ "Manager", "DefaultRestartSec", config_parse_sec, 0, &arg_default_restart_usec },
672706
{ "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval }, /* obsolete alias */
673707
{ "Manager", "DefaultStartLimitIntervalSec", config_parse_sec, 0, &arg_default_start_limit_interval },
@@ -699,6 +733,7 @@ static int parse_config_file(void) {
699733
{ "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_default_tasks_max },
700734
{ "Manager", "CtrlAltDelBurstAction", config_parse_emergency_action, 0, &arg_cad_burst_action },
701735
{ "Manager", "DefaultOOMPolicy", config_parse_oom_policy, 0, &arg_default_oom_policy },
736+
{ "Manager", "DefaultOOMScoreAdjust", config_parse_oom_score_adjust, 0, NULL },
702737
{}
703738
};
704739

@@ -769,6 +804,8 @@ static void set_manager_defaults(Manager *m) {
769804
m->default_tasks_accounting = arg_default_tasks_accounting;
770805
m->default_tasks_max = arg_default_tasks_max;
771806
m->default_oom_policy = arg_default_oom_policy;
807+
m->default_oom_score_adjust_set = arg_default_oom_score_adjust_set;
808+
m->default_oom_score_adjust = arg_default_oom_score_adjust;
772809

773810
(void) manager_set_default_rlimits(m, arg_default_rlimit);
774811

@@ -2426,6 +2463,35 @@ static void reset_arguments(void) {
24262463
arg_random_seed = mfree(arg_random_seed);
24272464
arg_random_seed_size = 0;
24282465
arg_clock_usec = 0;
2466+
2467+
arg_default_oom_score_adjust_set = false;
2468+
}
2469+
2470+
static void determine_default_oom_score_adjust(void) {
2471+
int r, a, b;
2472+
2473+
/* Run our services at slightly higher OOM score than ourselves. But let's be conservative here, and
2474+
* do this only if we don't run as root (i.e. only if we are run in user mode, for an unprivileged
2475+
* user). */
2476+
2477+
if (arg_default_oom_score_adjust_set)
2478+
return;
2479+
2480+
if (getuid() == 0)
2481+
return;
2482+
2483+
r = get_oom_score_adjust(&a);
2484+
if (r < 0)
2485+
return (void) log_warning_errno(r, "Failed to determine current OOM score adjustment value, ignoring: %m");
2486+
2487+
assert_cc(100 <= OOM_SCORE_ADJ_MAX);
2488+
b = a >= OOM_SCORE_ADJ_MAX - 100 ? OOM_SCORE_ADJ_MAX : a + 100;
2489+
2490+
if (a == b)
2491+
return;
2492+
2493+
arg_default_oom_score_adjust = b;
2494+
arg_default_oom_score_adjust_set = true;
24292495
}
24302496

24312497
static int parse_configuration(const struct rlimit *saved_rlimit_nofile,
@@ -2459,6 +2525,9 @@ static int parse_configuration(const struct rlimit *saved_rlimit_nofile,
24592525
if (arg_show_status == _SHOW_STATUS_INVALID)
24602526
arg_show_status = SHOW_STATUS_YES;
24612527

2528+
/* Slightly raise the OOM score for our services if we are running for unprivileged users. */
2529+
determine_default_oom_score_adjust();
2530+
24622531
/* Push variables into the manager environment block */
24632532
setenv_manager_environment();
24642533

src/core/manager.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,8 @@ struct Manager {
370370
usec_t default_timer_accuracy_usec;
371371

372372
OOMPolicy default_oom_policy;
373+
int default_oom_score_adjust;
374+
bool default_oom_score_adjust_set;
373375

374376
int original_log_level;
375377
LogTarget original_log_target;

src/core/unit.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,11 @@ static void unit_init(Unit *u) {
187187
if (ec) {
188188
exec_context_init(ec);
189189

190+
if (u->manager->default_oom_score_adjust_set) {
191+
ec->oom_score_adjust = u->manager->default_oom_score_adjust;
192+
ec->oom_score_adjust_set = true;
193+
}
194+
190195
if (MANAGER_IS_SYSTEM(u->manager))
191196
ec->keyring_mode = EXEC_KEYRING_SHARED;
192197
else {

0 commit comments

Comments
 (0)