pid1: also process memory pressure events (and SIGRTMIN+18)

This commit is contained in:
Lennart Poettering 2023-02-15 11:22:02 +01:00
parent ee32689f39
commit 29e6b0c171
3 changed files with 78 additions and 1 deletions

View 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;
}

View 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;

View 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);