|
3 | 3 | #include <errno.h> |
4 | 4 | #include <fcntl.h> |
5 | 5 | #include <getopt.h> |
| 6 | +#include <linux/oom.h> |
6 | 7 | #include <sys/mount.h> |
7 | 8 | #include <sys/prctl.h> |
8 | 9 | #include <sys/reboot.h> |
@@ -160,6 +161,8 @@ static NUMAPolicy arg_numa_policy; |
160 | 161 | static usec_t arg_clock_usec; |
161 | 162 | static void *arg_random_seed; |
162 | 163 | static size_t arg_random_seed_size; |
| 164 | +static int arg_default_oom_score_adjust; |
| 165 | +static bool arg_default_oom_score_adjust_set; |
163 | 166 |
|
164 | 167 | /* A copy of the original environment block */ |
165 | 168 | static char **saved_env = NULL; |
@@ -633,6 +636,37 @@ static int config_parse_default_timeout_abort( |
633 | 636 | return 0; |
634 | 637 | } |
635 | 638 |
|
| 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 | + |
636 | 670 | static int parse_config_file(void) { |
637 | 671 | const ConfigTableItem items[] = { |
638 | 672 | { "Manager", "LogLevel", config_parse_level2, 0, NULL }, |
@@ -667,7 +701,7 @@ static int parse_config_file(void) { |
667 | 701 | { "Manager", "DefaultStandardError", config_parse_output_restricted, 0, &arg_default_std_error }, |
668 | 702 | { "Manager", "DefaultTimeoutStartSec", config_parse_sec, 0, &arg_default_timeout_start_usec }, |
669 | 703 | { "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 }, |
671 | 705 | { "Manager", "DefaultRestartSec", config_parse_sec, 0, &arg_default_restart_usec }, |
672 | 706 | { "Manager", "DefaultStartLimitInterval", config_parse_sec, 0, &arg_default_start_limit_interval }, /* obsolete alias */ |
673 | 707 | { "Manager", "DefaultStartLimitIntervalSec", config_parse_sec, 0, &arg_default_start_limit_interval }, |
@@ -699,6 +733,7 @@ static int parse_config_file(void) { |
699 | 733 | { "Manager", "DefaultTasksMax", config_parse_tasks_max, 0, &arg_default_tasks_max }, |
700 | 734 | { "Manager", "CtrlAltDelBurstAction", config_parse_emergency_action, 0, &arg_cad_burst_action }, |
701 | 735 | { "Manager", "DefaultOOMPolicy", config_parse_oom_policy, 0, &arg_default_oom_policy }, |
| 736 | + { "Manager", "DefaultOOMScoreAdjust", config_parse_oom_score_adjust, 0, NULL }, |
702 | 737 | {} |
703 | 738 | }; |
704 | 739 |
|
@@ -769,6 +804,8 @@ static void set_manager_defaults(Manager *m) { |
769 | 804 | m->default_tasks_accounting = arg_default_tasks_accounting; |
770 | 805 | m->default_tasks_max = arg_default_tasks_max; |
771 | 806 | 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; |
772 | 809 |
|
773 | 810 | (void) manager_set_default_rlimits(m, arg_default_rlimit); |
774 | 811 |
|
@@ -2426,6 +2463,35 @@ static void reset_arguments(void) { |
2426 | 2463 | arg_random_seed = mfree(arg_random_seed); |
2427 | 2464 | arg_random_seed_size = 0; |
2428 | 2465 | 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; |
2429 | 2495 | } |
2430 | 2496 |
|
2431 | 2497 | static int parse_configuration(const struct rlimit *saved_rlimit_nofile, |
@@ -2459,6 +2525,9 @@ static int parse_configuration(const struct rlimit *saved_rlimit_nofile, |
2459 | 2525 | if (arg_show_status == _SHOW_STATUS_INVALID) |
2460 | 2526 | arg_show_status = SHOW_STATUS_YES; |
2461 | 2527 |
|
| 2528 | + /* Slightly raise the OOM score for our services if we are running for unprivileged users. */ |
| 2529 | + determine_default_oom_score_adjust(); |
| 2530 | + |
2462 | 2531 | /* Push variables into the manager environment block */ |
2463 | 2532 | setenv_manager_environment(); |
2464 | 2533 |
|
|
0 commit comments