From: Lennart Poettering Date: Wed, 15 Feb 2023 10:22:02 +0000 (+0100) Subject: pid1: also process memory pressure events (and SIGRTMIN+18) X-Git-Tag: v254-rc1~1142^2~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=29e6b0c171f49edb05e017a80bc90a61dfe82de0;p=thirdparty%2Fsystemd.git pid1: also process memory pressure events (and SIGRTMIN+18) --- diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 7ac9549f89e..441d1125d29 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -2362,6 +2362,13 @@ static int unit_update_cgroup( cgroup_context_apply(u, target_mask, state); cgroup_xattr_apply(u); + /* For most units we expect that memory monitoring is set up before the unit is started and we won't + * touch it after. For PID 1 this is different though, because we couldn't possibly do that given + * that PID 1 runs before init.scope is even set up. Hence, whenever init.scope is realized, let's + * try to open the memory pressure interface anew. */ + if (unit_has_name(u, SPECIAL_INIT_SCOPE)) + (void) manager_setup_memory_pressure_event_source(u->manager); + return 0; } diff --git a/src/core/manager.c b/src/core/manager.c index 5c8c417daed..8dd4f098912 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -31,6 +31,7 @@ #include "bus-util.h" #include "clean-ipc.h" #include "clock-util.h" +#include "common-signal.h" #include "constants.h" #include "core-varlink.h" #include "creds-util.h" @@ -567,7 +568,11 @@ static int manager_setup_signals(Manager *m) { SIGRTMIN+15, /* systemd: Immediate reboot */ SIGRTMIN+16, /* systemd: Immediate kexec */ - /* ... space for more immediate system state changes ... */ + /* ... space for one more immediate system state change ... */ + + SIGRTMIN+18, /* systemd: control command */ + + /* ... space ... */ SIGRTMIN+20, /* systemd: enable status messages */ SIGRTMIN+21, /* systemd: disable status messages */ @@ -787,6 +792,21 @@ static int manager_setup_sigchld_event_source(Manager *m) { return 0; } +int manager_setup_memory_pressure_event_source(Manager *m) { + int r; + + assert(m); + + m->memory_pressure_event_source = sd_event_source_disable_unref(m->memory_pressure_event_source); + + r = sd_event_add_memory_pressure(m->event, &m->memory_pressure_event_source, NULL, NULL); + if (r < 0) + log_full_errno(ERRNO_IS_NOT_SUPPORTED(r) || ERRNO_IS_PRIVILEGE(r) || (r == -EHOSTDOWN) ? LOG_DEBUG : LOG_NOTICE, r, + "Failed to establish memory pressure event source, ignoring: %m"); + + return 0; +} + static int manager_find_credentials_dirs(Manager *m) { const char *e; int r; @@ -967,6 +987,10 @@ int manager_new(LookupScope scope, ManagerTestRunFlags test_run_flags, Manager * if (r < 0) return r; + r = manager_setup_memory_pressure_event_source(m); + if (r < 0) + return r; + #if HAVE_LIBBPF if (MANAGER_IS_SYSTEM(m) && lsm_bpf_supported(/* initialize = */ true)) { r = lsm_bpf_setup(m); @@ -1541,6 +1565,7 @@ Manager* manager_free(Manager *m) { sd_event_source_unref(m->jobs_in_progress_event_source); sd_event_source_unref(m->run_queue_event_source); sd_event_source_unref(m->user_lookup_event_source); + sd_event_source_unref(m->memory_pressure_event_source); safe_close(m->signal_fd); safe_close(m->notify_fd); @@ -2892,6 +2917,47 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t switch (sfsi.ssi_signo - SIGRTMIN) { + case 18: { + bool generic = false; + + if (sfsi.ssi_code != SI_QUEUE) + generic = true; + else { + /* Override a few select commands by our own PID1-specific logic */ + + switch (sfsi.ssi_int) { + + case _COMMON_SIGNAL_COMMAND_LOG_LEVEL_BASE..._COMMON_SIGNAL_COMMAND_LOG_LEVEL_END: + manager_override_log_level(m, sfsi.ssi_int - _COMMON_SIGNAL_COMMAND_LOG_LEVEL_BASE); + break; + + case COMMON_SIGNAL_COMMAND_CONSOLE: + manager_override_log_target(m, LOG_TARGET_CONSOLE); + break; + + case COMMON_SIGNAL_COMMAND_JOURNAL: + manager_override_log_target(m, LOG_TARGET_JOURNAL); + break; + + case COMMON_SIGNAL_COMMAND_KMSG: + manager_override_log_target(m, LOG_TARGET_KMSG); + break; + + case COMMON_SIGNAL_COMMAND_NULL: + manager_override_log_target(m, LOG_TARGET_NULL); + break; + + default: + generic = true; + } + } + + if (generic) + return sigrtmin18_handler(source, &sfsi, NULL); + + break; + } + case 20: manager_override_show_status(m, SHOW_STATUS_YES, "signal"); break; diff --git a/src/core/manager.h b/src/core/manager.h index e7b594fdd30..66e6a9e1cfc 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -464,6 +464,8 @@ struct Manager { /* Allow users to configure a rate limit for Reload() operations */ RateLimit reload_ratelimit; + + sd_event_source *memory_pressure_event_source; }; static inline usec_t manager_default_timeout_abort_usec(Manager *m) { @@ -517,6 +519,8 @@ void manager_unwatch_pid(Manager *m, pid_t pid); unsigned manager_dispatch_load_queue(Manager *m); +int manager_setup_memory_pressure_event_source(Manager *m); + int manager_default_environment(Manager *m); int manager_transient_environment_add(Manager *m, char **plus); int manager_client_environment_modify(Manager *m, char **minus, char **plus);