]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
pid1: also process memory pressure events (and SIGRTMIN+18)
authorLennart Poettering <lennart@poettering.net>
Wed, 15 Feb 2023 10:22:02 +0000 (11:22 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 1 Mar 2023 08:43:23 +0000 (09:43 +0100)
src/core/cgroup.c
src/core/manager.c
src/core/manager.h

index 7ac9549f89ed6edc84537292cd8757b4fc166cd3..441d1125d2964ce4f18b80c2389ec915a5cf3b5d 100644 (file)
@@ -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;
 }
 
index 5c8c417daedf3569c1bb0f3d147a10e36bfb30a7..8dd4f09891260a772d986a8c03575f906c684f2f 100644 (file)
@@ -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;
index e7b594fdd30081506e81ad438a671dd56cb4cf1a..66e6a9e1cfc4b782f8fba3ad916fdb9b35032714 100644 (file)
@@ -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);