From 1961d84ab55c18cfd908a3a80d60455aea96f369 Mon Sep 17 00:00:00 2001 From: msizanoen1 Date: Jun 02 2022 18:07:11 +0000 Subject: cgroup-util: Properly handle conditions where cgroup.threads is empty after SIGKILL but processes still remain After sending a SIGKILL to a process, the process might disappear from `cgroup.threads` but still show up in `cgroup.procs` and still remains in the cgroup and cause migrating new processes to `Delegate=yes` cgroups to fail with `-EBUSY`. This is especially likely for heavyweight processes that consume more kernel CPU time to clean up. Fix this by only returning 0 when both `cgroup.threads` and `cgroup.procs` are empty. (cherry picked from commit 37f0289bf5f2283c187032f83c33ea955b75f119) --- diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 95bf177..b03cc70 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -357,20 +357,29 @@ int cg_kill( Set *s, cg_kill_log_func_t log_kill, void *userdata) { - int r; + + int r, ret; r = cg_kill_items(controller, path, sig, flags, s, log_kill, userdata, "cgroup.procs"); if (r < 0 || sig != SIGKILL) return r; + ret = r; + /* Only in case of killing with SIGKILL and when using cgroupsv2, kill remaining threads manually as a workaround for kernel bug. It was fixed in 5.2-rc5 (c03cd7738a83), backported to 4.19.66 (4340d175b898) and 4.14.138 (feb6b123b7dd). */ r = cg_unified_controller(controller); - if (r <= 0) + if (r < 0) + return r; + if (r == 0) + return ret; + + r = cg_kill_items(controller, path, sig, flags, s, log_kill, userdata, "cgroup.threads"); + if (r < 0) return r; - return cg_kill_items(controller, path, sig, flags, s, log_kill, userdata, "cgroup.threads"); + return r > 0 || ret > 0; } int cg_kill_kernel_sigkill(const char *controller, const char *path) {