]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
oom: use cgroup.kill if available 42373/head
authorLuca Boccassi <luca.boccassi@gmail.com>
Thu, 28 May 2026 18:24:36 +0000 (19:24 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Fri, 29 May 2026 11:02:29 +0000 (12:02 +0100)
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.

src/oom/oomd-util.c

index 4128d315a635e027150e1ed44b3e8384457537c5..d488277c47b5a5996cd72b29c13a0895b5cef240 100644 (file)
@@ -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) {