From: Luca Boccassi Date: Thu, 28 May 2026 18:24:36 +0000 (+0100) Subject: oom: use cgroup.kill if available X-Git-Tag: v261-rc4~60^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F42373%2Fhead;p=thirdparty%2Fsystemd.git oom: use cgroup.kill if available The log message is informational only, same as the count of killed processes, so we can safely use cgroup.kill when available instead of manually recursing through the cgroup tree. --- diff --git a/src/oom/oomd-util.c b/src/oom/oomd-util.c index 4128d315a63..d488277c47b 100644 --- a/src/oom/oomd-util.c +++ b/src/oom/oomd-util.c @@ -14,6 +14,7 @@ #include "parse-util.h" #include "path-util.h" #include "pidref.h" +#include "process-util.h" #include "procfs-util.h" #include "sd-bus.h" #include "set.h" @@ -249,24 +250,46 @@ int oomd_sort_cgroup_contexts(Hashmap *h, oomd_compare_t compare_func, const cha } int oomd_cgroup_kill(Manager *m, OomdCGroupContext *ctx, bool recurse, const char *reason) { - _cleanup_set_free_ Set *pids_killed = NULL; + _cleanup_free_ char *cg_path_self = NULL; + uint64_t n_pids_killed = UINT64_MAX; int r; assert(ctx); assert(!m || reason); - pids_killed = set_new(NULL); - if (!pids_killed) - return -ENOMEM; + /* Just for safety, in case group.kill is used */ + r = cg_pid_get_path(getpid_cached(), &cg_path_self); + if (r < 0) + log_debug_errno(r, "Failed to get cgroup path for self, ignoring: %m"); + else if (streq(cg_path_self, ctx->path)) { + log_debug("Skipping own cgroup '%s'", ctx->path); + return 0; + } r = increment_oomd_xattr(ctx->path, "user.oomd_ooms", 1); if (r < 0) log_debug_errno(r, "Failed to set user.oomd_ooms before kill: %m"); - if (recurse) - r = cg_kill_recursive(ctx->path, SIGKILL, CGROUP_IGNORE_SELF, pids_killed, log_kill, NULL); - else - r = cg_kill(ctx->path, SIGKILL, CGROUP_IGNORE_SELF, pids_killed, log_kill, NULL); + if (recurse) { + r = cg_kill_kernel_sigkill(ctx->path, &n_pids_killed); + if (r == -EOPNOTSUPP) { + _cleanup_set_free_ Set *pids_killed = set_new(/* hash_ops= */ NULL); + if (!pids_killed) + return -ENOMEM; + + r = cg_kill_recursive(ctx->path, SIGKILL, CGROUP_IGNORE_SELF, pids_killed, log_kill, /* userdata= */ NULL); + if (r >= 0) + n_pids_killed = set_size(pids_killed); + } + } else { + _cleanup_set_free_ Set *pids_killed = set_new(/* hash_ops= */ NULL); + if (!pids_killed) + return -ENOMEM; + + r = cg_kill(ctx->path, SIGKILL, CGROUP_IGNORE_SELF, pids_killed, log_kill, /* userdata= */ NULL); + if (r >= 0) + n_pids_killed = set_size(pids_killed); + } /* The cgroup could have been cleaned up after we have sent SIGKILL to all of the processes, but before * we could do one last iteration of cgroup.procs to check. Or the service unit could have exited and @@ -277,12 +300,13 @@ int oomd_cgroup_kill(Manager *m, OomdCGroupContext *ctx, bool recurse, const cha else if (r < 0) return r; - if (set_isempty(pids_killed)) + if (n_pids_killed == 0) log_debug("Nothing killed when attempting to kill %s", ctx->path); - - r = increment_oomd_xattr(ctx->path, "user.oomd_kill", set_size(pids_killed)); - if (r < 0) - log_debug_errno(r, "Failed to set user.oomd_kill on kill: %m"); + else if (n_pids_killed != UINT64_MAX) { + r = increment_oomd_xattr(ctx->path, "user.oomd_kill", n_pids_killed); + if (r < 0) + log_debug_errno(r, "Failed to set user.oomd_kill on kill, ignoring: %m"); + } /* send dbus signal */ if (m) @@ -294,7 +318,7 @@ int oomd_cgroup_kill(Manager *m, OomdCGroupContext *ctx, bool recurse, const cha ctx->path, reason); - return !set_isempty(pids_killed); + return n_pids_killed > 0 && n_pids_killed != UINT64_MAX; } static void oomd_kill_state_free(OomdKillState *ks) {