From: Luca Boccassi Date: Thu, 28 May 2026 18:15:33 +0000 (+0100) Subject: cgroup: optionally check number of tasks before cgroup.kill X-Git-Tag: v261-rc4~60^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=92a5bf2c0205f5b0cf66d2913cb88e567a95ba1c;p=thirdparty%2Fsystemd.git cgroup: optionally check number of tasks before cgroup.kill This of course cannot be atomic, but for informational purposes it should be good enough --- diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 6a40ede29ed..aac0f035eba 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -406,8 +406,9 @@ int cg_kill_recursive( return ret; } -int cg_kill_kernel_sigkill(const char *path) { +int cg_kill_kernel_sigkill(const char *path, uint64_t *ret_n_pids_killed) { _cleanup_free_ char *killfile = NULL; + uint64_t n_pids = UINT64_MAX; int r; /* Kills the cgroup at `path` directly by writing to its cgroup.kill file. This sends SIGKILL to all @@ -422,10 +423,22 @@ int cg_kill_kernel_sigkill(const char *path) { if (r < 0) return r; + if (ret_n_pids_killed) { + /* This is not and cannot be atomic so there is a chance the counter might not be accurate + * if a process starts/stops between this read and the next write, but this is used for + * informational purposes so that's ok. */ + r = cg_get_attribute_as_uint64(path, "pids.current", &n_pids); + if (r < 0) + log_debug_errno(r, "Failed to read pids.current from cgroup '%s', ignoring: %m", path); + } + r = write_string_file(killfile, "1", WRITE_STRING_FILE_DISABLE_BUFFER); if (r < 0) return log_debug_errno(r, "Failed to write to cgroup.kill for cgroup '%s': %m", path); + if (ret_n_pids_killed) + *ret_n_pids_killed = n_pids; + return 0; } diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h index 7cf0f779b8b..2c438167f10 100644 --- a/src/basic/cgroup-util.h +++ b/src/basic/cgroup-util.h @@ -142,7 +142,7 @@ int cg_read_subgroup(DIR *d, char **ret); typedef int (*cg_kill_log_func_t)(const PidRef *pid, int sig, void *userdata); int cg_kill(const char *path, int sig, CGroupFlags flags, Set *killed_pids, cg_kill_log_func_t log_kill, void *userdata); -int cg_kill_kernel_sigkill(const char *path); +int cg_kill_kernel_sigkill(const char *path, uint64_t *ret_n_pids_killed); int cg_kill_recursive(const char *path, int sig, CGroupFlags flags, Set *killed_pids, cg_kill_log_func_t log_kill, void *userdata); int cg_split_spec(const char *spec, char **ret_controller, char **ret_path); diff --git a/src/core/unit.c b/src/core/unit.c index d66f813a9a3..b5a3951c969 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -4158,7 +4158,7 @@ int unit_kill( } if (signo == SIGKILL) { - r = cg_kill_kernel_sigkill(p); + r = cg_kill_kernel_sigkill(p, /* ret_n_pids_killed= */ NULL); if (r >= 0) { killed = true; log_unit_info(u, "Killed unit cgroup '%s' with SIGKILL on client request.", p);