summaryrefslogtreecommitdiff
path: root/src/basic/cgroup-util.c
diff options
context:
space:
mode:
authormsizanoen1 <msizanoen@qtmlabs.xyz>2022-05-30 22:08:07 +0700
committerYu Watanabe <watanabe.yu+github@gmail.com>2022-05-31 05:03:31 +0900
commit37f0289bf5f2283c187032f83c33ea955b75f119 (patch)
tree16c839db0a8d7444ea836369863534691b1fddc9 /src/basic/cgroup-util.c
parent9a18321058f6be28cccb97fd8f1d70bcbc1e237d (diff)
downloadsystemd-37f0289bf5f2283c187032f83c33ea955b75f119.tar.gz
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.
Diffstat (limited to 'src/basic/cgroup-util.c')
-rw-r--r--src/basic/cgroup-util.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
index 95bf177a6b..b03cc70e2e 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) {