mirror of
https://github.com/systemd/systemd.git
synced 2024-12-25 01:34:28 +03:00
cgroup-util: kill also threads
It's possible for a zombie process to have live threads. These are not listed in /sys in "cgroup.procs" for cgroupsv2, but they show up in "cgroup.threads" (cgroupv2) or "tasks" (cgroupv1) nodes. When killing a cgroup (v2 only) with SIGKILL, let's also kill threads after killing processes, so the live threads of a zombie get killed too. Closes #12262.
This commit is contained in:
parent
0127b1a05e
commit
e48fcfef06
@ -43,14 +43,14 @@
|
||||
#include "unit-name.h"
|
||||
#include "user-util.h"
|
||||
|
||||
int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
|
||||
static int cg_enumerate_items(const char *controller, const char *path, FILE **_f, const char *item) {
|
||||
_cleanup_free_ char *fs = NULL;
|
||||
FILE *f;
|
||||
int r;
|
||||
|
||||
assert(_f);
|
||||
|
||||
r = cg_get_path(controller, path, "cgroup.procs", &fs);
|
||||
r = cg_get_path(controller, path, item, &fs);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -62,6 +62,10 @@ int cg_enumerate_processes(const char *controller, const char *path, FILE **_f)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
|
||||
return cg_enumerate_items(controller, path, _f, "cgroup.procs");
|
||||
}
|
||||
|
||||
int cg_read_pid(FILE *f, pid_t *_pid) {
|
||||
unsigned long ul;
|
||||
|
||||
@ -221,14 +225,15 @@ int cg_rmdir(const char *controller, const char *path) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cg_kill(
|
||||
static int cg_kill_items(
|
||||
const char *controller,
|
||||
const char *path,
|
||||
int sig,
|
||||
CGroupFlags flags,
|
||||
Set *s,
|
||||
cg_kill_log_func_t log_kill,
|
||||
void *userdata) {
|
||||
void *userdata,
|
||||
const char *item) {
|
||||
|
||||
_cleanup_set_free_ Set *allocated_set = NULL;
|
||||
bool done = false;
|
||||
@ -259,7 +264,7 @@ int cg_kill(
|
||||
pid_t pid = 0;
|
||||
done = true;
|
||||
|
||||
r = cg_enumerate_processes(controller, path, &f);
|
||||
r = cg_enumerate_items(controller, path, &f, item);
|
||||
if (r < 0) {
|
||||
if (ret >= 0 && r != -ENOENT)
|
||||
return r;
|
||||
@ -322,6 +327,31 @@ int cg_kill(
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cg_kill(
|
||||
const char *controller,
|
||||
const char *path,
|
||||
int sig,
|
||||
CGroupFlags flags,
|
||||
Set *s,
|
||||
cg_kill_log_func_t log_kill,
|
||||
void *userdata) {
|
||||
int r;
|
||||
|
||||
r = cg_kill_items(controller, path, sig, flags, s, log_kill, userdata, "cgroup.procs");
|
||||
if (r < 0 || sig != SIGKILL)
|
||||
return 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). */
|
||||
r = cg_unified_controller(controller);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) /* doesn't apply to legacy hierarchy */
|
||||
return 0;
|
||||
|
||||
return cg_kill_items(controller, path, sig, flags, s, log_kill, userdata, "cgroup.threads");
|
||||
}
|
||||
|
||||
int cg_kill_recursive(
|
||||
const char *controller,
|
||||
const char *path,
|
||||
|
Loading…
Reference in New Issue
Block a user