Merge pull request #3762 from poettering/sigkill-log
log about all processes we forcibly kill
This commit is contained in:
+48
-21
@@ -197,7 +197,15 @@ int cg_rmdir(const char *controller, const char *path) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) {
|
||||
int cg_kill(
|
||||
const char *controller,
|
||||
const char *path,
|
||||
int sig,
|
||||
CGroupFlags flags,
|
||||
Set *s,
|
||||
cg_kill_log_func_t log_kill,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_set_free_ Set *allocated_set = NULL;
|
||||
bool done = false;
|
||||
int r, ret = 0;
|
||||
@@ -205,6 +213,11 @@ int cg_kill(const char *controller, const char *path, int sig, bool sigcont, boo
|
||||
|
||||
assert(sig >= 0);
|
||||
|
||||
/* Don't send SIGCONT twice. Also, SIGKILL always works even when process is suspended, hence don't send
|
||||
* SIGCONT on SIGKILL. */
|
||||
if (IN_SET(sig, SIGCONT, SIGKILL))
|
||||
flags &= ~CGROUP_SIGCONT;
|
||||
|
||||
/* This goes through the tasks list and kills them all. This
|
||||
* is repeated until no further processes are added to the
|
||||
* tasks list, to properly handle forking processes */
|
||||
@@ -232,19 +245,22 @@ int cg_kill(const char *controller, const char *path, int sig, bool sigcont, boo
|
||||
|
||||
while ((r = cg_read_pid(f, &pid)) > 0) {
|
||||
|
||||
if (ignore_self && pid == my_pid)
|
||||
if ((flags & CGROUP_IGNORE_SELF) && pid == my_pid)
|
||||
continue;
|
||||
|
||||
if (set_get(s, PID_TO_PTR(pid)) == PID_TO_PTR(pid))
|
||||
continue;
|
||||
|
||||
if (log_kill)
|
||||
log_kill(pid, sig, userdata);
|
||||
|
||||
/* If we haven't killed this process yet, kill
|
||||
* it */
|
||||
if (kill(pid, sig) < 0) {
|
||||
if (ret >= 0 && errno != ESRCH)
|
||||
ret = -errno;
|
||||
} else {
|
||||
if (sigcont && sig != SIGKILL)
|
||||
if (flags & CGROUP_SIGCONT)
|
||||
(void) kill(pid, SIGCONT);
|
||||
|
||||
if (ret == 0)
|
||||
@@ -278,7 +294,15 @@ int cg_kill(const char *controller, const char *path, int sig, bool sigcont, boo
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) {
|
||||
int cg_kill_recursive(
|
||||
const char *controller,
|
||||
const char *path,
|
||||
int sig,
|
||||
CGroupFlags flags,
|
||||
Set *s,
|
||||
cg_kill_log_func_t log_kill,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_set_free_ Set *allocated_set = NULL;
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
int r, ret;
|
||||
@@ -293,7 +317,7 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool si
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = cg_kill(controller, path, sig, sigcont, ignore_self, s);
|
||||
ret = cg_kill(controller, path, sig, flags, s, log_kill, userdata);
|
||||
|
||||
r = cg_enumerate_subgroups(controller, path, &d);
|
||||
if (r < 0) {
|
||||
@@ -311,15 +335,14 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool si
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s);
|
||||
r = cg_kill_recursive(controller, p, sig, flags, s, log_kill, userdata);
|
||||
if (r != 0 && ret >= 0)
|
||||
ret = r;
|
||||
}
|
||||
|
||||
if (ret >= 0 && r < 0)
|
||||
ret = r;
|
||||
|
||||
if (rem) {
|
||||
if (flags & CGROUP_REMOVE) {
|
||||
r = cg_rmdir(controller, path);
|
||||
if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
|
||||
return r;
|
||||
@@ -328,7 +351,13 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool si
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self) {
|
||||
int cg_migrate(
|
||||
const char *cfrom,
|
||||
const char *pfrom,
|
||||
const char *cto,
|
||||
const char *pto,
|
||||
CGroupFlags flags) {
|
||||
|
||||
bool done = false;
|
||||
_cleanup_set_free_ Set *s = NULL;
|
||||
int r, ret = 0;
|
||||
@@ -363,7 +392,7 @@ int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char
|
||||
/* This might do weird stuff if we aren't a
|
||||
* single-threaded program. However, we
|
||||
* luckily know we are not */
|
||||
if (ignore_self && pid == my_pid)
|
||||
if ((flags & CGROUP_IGNORE_SELF) && pid == my_pid)
|
||||
continue;
|
||||
|
||||
if (set_get(s, PID_TO_PTR(pid)) == PID_TO_PTR(pid))
|
||||
@@ -411,8 +440,7 @@ int cg_migrate_recursive(
|
||||
const char *pfrom,
|
||||
const char *cto,
|
||||
const char *pto,
|
||||
bool ignore_self,
|
||||
bool rem) {
|
||||
CGroupFlags flags) {
|
||||
|
||||
_cleanup_closedir_ DIR *d = NULL;
|
||||
int r, ret = 0;
|
||||
@@ -423,7 +451,7 @@ int cg_migrate_recursive(
|
||||
assert(cto);
|
||||
assert(pto);
|
||||
|
||||
ret = cg_migrate(cfrom, pfrom, cto, pto, ignore_self);
|
||||
ret = cg_migrate(cfrom, pfrom, cto, pto, flags);
|
||||
|
||||
r = cg_enumerate_subgroups(cfrom, pfrom, &d);
|
||||
if (r < 0) {
|
||||
@@ -441,7 +469,7 @@ int cg_migrate_recursive(
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
r = cg_migrate_recursive(cfrom, p, cto, pto, ignore_self, rem);
|
||||
r = cg_migrate_recursive(cfrom, p, cto, pto, flags);
|
||||
if (r != 0 && ret >= 0)
|
||||
ret = r;
|
||||
}
|
||||
@@ -449,7 +477,7 @@ int cg_migrate_recursive(
|
||||
if (r < 0 && ret >= 0)
|
||||
ret = r;
|
||||
|
||||
if (rem) {
|
||||
if (flags & CGROUP_REMOVE) {
|
||||
r = cg_rmdir(cfrom, pfrom);
|
||||
if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
|
||||
return r;
|
||||
@@ -463,8 +491,7 @@ int cg_migrate_recursive_fallback(
|
||||
const char *pfrom,
|
||||
const char *cto,
|
||||
const char *pto,
|
||||
bool ignore_self,
|
||||
bool rem) {
|
||||
CGroupFlags flags) {
|
||||
|
||||
int r;
|
||||
|
||||
@@ -473,7 +500,7 @@ int cg_migrate_recursive_fallback(
|
||||
assert(cto);
|
||||
assert(pto);
|
||||
|
||||
r = cg_migrate_recursive(cfrom, pfrom, cto, pto, ignore_self, rem);
|
||||
r = cg_migrate_recursive(cfrom, pfrom, cto, pto, flags);
|
||||
if (r < 0) {
|
||||
char prefix[strlen(pto) + 1];
|
||||
|
||||
@@ -482,7 +509,7 @@ int cg_migrate_recursive_fallback(
|
||||
PATH_FOREACH_PREFIX(prefix, pto) {
|
||||
int q;
|
||||
|
||||
q = cg_migrate_recursive(cfrom, pfrom, cto, prefix, ignore_self, rem);
|
||||
q = cg_migrate_recursive(cfrom, pfrom, cto, prefix, flags);
|
||||
if (q >= 0)
|
||||
return q;
|
||||
}
|
||||
@@ -1955,7 +1982,7 @@ int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to
|
||||
int r = 0, unified;
|
||||
|
||||
if (!path_equal(from, to)) {
|
||||
r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true);
|
||||
r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, CGROUP_REMOVE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@@ -1979,7 +2006,7 @@ int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to
|
||||
if (!p)
|
||||
p = to;
|
||||
|
||||
(void) cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, cgroup_controller_to_string(c), p, false, false);
|
||||
(void) cg_migrate_recursive_fallback(SYSTEMD_CGROUP_CONTROLLER, to, cgroup_controller_to_string(c), p, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+13
-5
@@ -135,12 +135,20 @@ int cg_read_event(const char *controller, const char *path, const char *event,
|
||||
int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d);
|
||||
int cg_read_subgroup(DIR *d, char **fn);
|
||||
|
||||
int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s);
|
||||
int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool remove, Set *s);
|
||||
typedef enum CGroupFlags {
|
||||
CGROUP_SIGCONT = 1,
|
||||
CGROUP_IGNORE_SELF = 2,
|
||||
CGROUP_REMOVE = 4,
|
||||
} CGroupFlags;
|
||||
|
||||
int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self);
|
||||
int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool remove);
|
||||
int cg_migrate_recursive_fallback(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self, bool rem);
|
||||
typedef void (*cg_kill_log_func_t)(pid_t pid, int sig, void *userdata);
|
||||
|
||||
int cg_kill(const char *controller, const char *path, int sig, CGroupFlags flags, Set *s, cg_kill_log_func_t kill_log, void *userdata);
|
||||
int cg_kill_recursive(const char *controller, const char *path, int sig, CGroupFlags flags, Set *s, cg_kill_log_func_t kill_log, void *userdata);
|
||||
|
||||
int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags);
|
||||
int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags);
|
||||
int cg_migrate_recursive_fallback(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags);
|
||||
|
||||
int cg_split_spec(const char *spec, char **controller, char **path);
|
||||
int cg_mangle_path(const char *path, char **result);
|
||||
|
||||
@@ -625,8 +625,10 @@ int kill_and_sigcont(pid_t pid, int sig) {
|
||||
|
||||
r = kill(pid, sig) < 0 ? -errno : 0;
|
||||
|
||||
if (r >= 0)
|
||||
kill(pid, SIGCONT);
|
||||
/* If this worked, also send SIGCONT, unless we already just sent a SIGCONT, or SIGKILL was sent which isn't
|
||||
* affected by a process being suspended anyway. */
|
||||
if (r >= 0 && !IN_SET(SIGCONT, SIGKILL))
|
||||
(void) kill(pid, SIGCONT);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1705,7 +1705,7 @@ int manager_setup_cgroup(Manager *m) {
|
||||
|
||||
/* also, move all other userspace processes remaining
|
||||
* in the root cgroup into that scope. */
|
||||
r = cg_migrate(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, SYSTEMD_CGROUP_CONTROLLER, scope_path, false);
|
||||
r = cg_migrate(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Couldn't move remaining userspace processes, ignoring: %m");
|
||||
|
||||
|
||||
@@ -225,5 +225,5 @@ int bus_scope_send_request_stop(Scope *s) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return sd_bus_send_to(UNIT(s)->manager->api_bus, m, /* s->controller */ NULL, NULL);
|
||||
return sd_bus_send_to(UNIT(s)->manager->api_bus, m, s->controller, NULL);
|
||||
}
|
||||
|
||||
+14
-2
@@ -240,7 +240,7 @@ static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
|
||||
|
||||
/* If we have a controller set let's ask the controller nicely
|
||||
* to terminate the scope, instead of us going directly into
|
||||
* SIGTERM beserk mode */
|
||||
* SIGTERM berserk mode */
|
||||
if (state == SCOPE_STOP_SIGTERM)
|
||||
skip_signal = bus_scope_send_request_stop(s) > 0;
|
||||
|
||||
@@ -248,7 +248,9 @@ static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
|
||||
r = unit_kill_context(
|
||||
UNIT(s),
|
||||
&s->kill_context,
|
||||
state != SCOPE_STOP_SIGTERM ? KILL_KILL : KILL_TERMINATE,
|
||||
state != SCOPE_STOP_SIGTERM ? KILL_KILL :
|
||||
s->was_abandoned ? KILL_TERMINATE_AND_LOG :
|
||||
KILL_TERMINATE,
|
||||
-1, -1, false);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
@@ -369,6 +371,7 @@ static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
|
||||
assert(fds);
|
||||
|
||||
unit_serialize_item(u, f, "state", scope_state_to_string(s->state));
|
||||
unit_serialize_item(u, f, "was-abandoned", yes_no(s->was_abandoned));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -389,6 +392,14 @@ static int scope_deserialize_item(Unit *u, const char *key, const char *value, F
|
||||
else
|
||||
s->deserialized_state = state;
|
||||
|
||||
} else if (streq(key, "was-abandoned")) {
|
||||
int k;
|
||||
|
||||
k = parse_boolean(value);
|
||||
if (k < 0)
|
||||
log_unit_debug(u, "Failed to parse boolean value: %s", value);
|
||||
else
|
||||
s->was_abandoned = k;
|
||||
} else
|
||||
log_unit_debug(u, "Unknown serialization key: %s", key);
|
||||
|
||||
@@ -474,6 +485,7 @@ int scope_abandon(Scope *s) {
|
||||
if (!IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED))
|
||||
return -ESTALE;
|
||||
|
||||
s->was_abandoned = true;
|
||||
s->controller = mfree(s->controller);
|
||||
|
||||
/* The client is no longer watching the remaining processes,
|
||||
|
||||
@@ -45,6 +45,7 @@ struct Scope {
|
||||
usec_t timeout_stop_usec;
|
||||
|
||||
char *controller;
|
||||
bool was_abandoned;
|
||||
|
||||
sd_event_source *timer_event_source;
|
||||
};
|
||||
|
||||
+1
-1
@@ -1674,7 +1674,7 @@ static void service_kill_control_processes(Service *s) {
|
||||
return;
|
||||
|
||||
p = strjoina(UNIT(s)->cgroup_path, "/control");
|
||||
cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, p, SIGKILL, true, true, true, NULL);
|
||||
cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, p, SIGKILL, CGROUP_SIGCONT|CGROUP_IGNORE_SELF|CGROUP_REMOVE, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static void service_enter_start(Service *s) {
|
||||
|
||||
+74
-24
@@ -3144,7 +3144,7 @@ int unit_kill_common(
|
||||
if (!pid_set)
|
||||
return -ENOMEM;
|
||||
|
||||
q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, false, false, pid_set);
|
||||
q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, 0, pid_set, NULL, NULL);
|
||||
if (q < 0 && q != -EAGAIN && q != -ESRCH && q != -ENOENT)
|
||||
r = q;
|
||||
else
|
||||
@@ -3512,6 +3512,43 @@ int unit_make_transient(Unit *u) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void log_kill(pid_t pid, int sig, void *userdata) {
|
||||
_cleanup_free_ char *comm = NULL;
|
||||
|
||||
(void) get_process_comm(pid, &comm);
|
||||
|
||||
/* Don't log about processes marked with brackets, under the assumption that these are temporary processes
|
||||
only, like for example systemd's own PAM stub process. */
|
||||
if (comm && comm[0] == '(')
|
||||
return;
|
||||
|
||||
log_unit_notice(userdata,
|
||||
"Killing process " PID_FMT " (%s) with signal SIG%s.",
|
||||
pid,
|
||||
strna(comm),
|
||||
signal_to_string(sig));
|
||||
}
|
||||
|
||||
static int operation_to_signal(KillContext *c, KillOperation k) {
|
||||
assert(c);
|
||||
|
||||
switch (k) {
|
||||
|
||||
case KILL_TERMINATE:
|
||||
case KILL_TERMINATE_AND_LOG:
|
||||
return c->kill_signal;
|
||||
|
||||
case KILL_KILL:
|
||||
return SIGKILL;
|
||||
|
||||
case KILL_ABORT:
|
||||
return SIGABRT;
|
||||
|
||||
default:
|
||||
assert_not_reached("KillOperation unknown");
|
||||
}
|
||||
}
|
||||
|
||||
int unit_kill_context(
|
||||
Unit *u,
|
||||
KillContext *c,
|
||||
@@ -3520,58 +3557,63 @@ int unit_kill_context(
|
||||
pid_t control_pid,
|
||||
bool main_pid_alien) {
|
||||
|
||||
bool wait_for_exit = false;
|
||||
bool wait_for_exit = false, send_sighup;
|
||||
cg_kill_log_func_t log_func;
|
||||
int sig, r;
|
||||
|
||||
assert(u);
|
||||
assert(c);
|
||||
|
||||
/* Kill the processes belonging to this unit, in preparation for shutting the unit down. Returns > 0 if we
|
||||
* killed something worth waiting for, 0 otherwise. */
|
||||
|
||||
if (c->kill_mode == KILL_NONE)
|
||||
return 0;
|
||||
|
||||
switch (k) {
|
||||
case KILL_KILL:
|
||||
sig = SIGKILL;
|
||||
break;
|
||||
case KILL_ABORT:
|
||||
sig = SIGABRT;
|
||||
break;
|
||||
case KILL_TERMINATE:
|
||||
sig = c->kill_signal;
|
||||
break;
|
||||
default:
|
||||
assert_not_reached("KillOperation unknown");
|
||||
}
|
||||
sig = operation_to_signal(c, k);
|
||||
|
||||
send_sighup =
|
||||
c->send_sighup &&
|
||||
IN_SET(k, KILL_TERMINATE, KILL_TERMINATE_AND_LOG) &&
|
||||
sig != SIGHUP;
|
||||
|
||||
log_func =
|
||||
k != KILL_TERMINATE ||
|
||||
IN_SET(sig, SIGKILL, SIGABRT) ? log_kill : NULL;
|
||||
|
||||
if (main_pid > 0) {
|
||||
r = kill_and_sigcont(main_pid, sig);
|
||||
if (log_func)
|
||||
log_func(main_pid, sig, u);
|
||||
|
||||
r = kill_and_sigcont(main_pid, sig);
|
||||
if (r < 0 && r != -ESRCH) {
|
||||
_cleanup_free_ char *comm = NULL;
|
||||
get_process_comm(main_pid, &comm);
|
||||
(void) get_process_comm(main_pid, &comm);
|
||||
|
||||
log_unit_warning_errno(u, r, "Failed to kill main process " PID_FMT " (%s), ignoring: %m", main_pid, strna(comm));
|
||||
} else {
|
||||
if (!main_pid_alien)
|
||||
wait_for_exit = true;
|
||||
|
||||
if (c->send_sighup && k == KILL_TERMINATE)
|
||||
if (r != -ESRCH && send_sighup)
|
||||
(void) kill(main_pid, SIGHUP);
|
||||
}
|
||||
}
|
||||
|
||||
if (control_pid > 0) {
|
||||
r = kill_and_sigcont(control_pid, sig);
|
||||
if (log_func)
|
||||
log_func(control_pid, sig, u);
|
||||
|
||||
r = kill_and_sigcont(control_pid, sig);
|
||||
if (r < 0 && r != -ESRCH) {
|
||||
_cleanup_free_ char *comm = NULL;
|
||||
get_process_comm(control_pid, &comm);
|
||||
(void) get_process_comm(control_pid, &comm);
|
||||
|
||||
log_unit_warning_errno(u, r, "Failed to kill control process " PID_FMT " (%s), ignoring: %m", control_pid, strna(comm));
|
||||
} else {
|
||||
wait_for_exit = true;
|
||||
|
||||
if (c->send_sighup && k == KILL_TERMINATE)
|
||||
if (r != -ESRCH && send_sighup)
|
||||
(void) kill(control_pid, SIGHUP);
|
||||
}
|
||||
}
|
||||
@@ -3585,7 +3627,11 @@ int unit_kill_context(
|
||||
if (!pid_set)
|
||||
return -ENOMEM;
|
||||
|
||||
r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, sig, true, k != KILL_TERMINATE, false, pid_set);
|
||||
r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path,
|
||||
sig,
|
||||
CGROUP_SIGCONT|CGROUP_IGNORE_SELF,
|
||||
pid_set,
|
||||
log_func, u);
|
||||
if (r < 0) {
|
||||
if (r != -EAGAIN && r != -ESRCH && r != -ENOENT)
|
||||
log_unit_warning_errno(u, r, "Failed to kill control group %s, ignoring: %m", u->cgroup_path);
|
||||
@@ -3610,14 +3656,18 @@ int unit_kill_context(
|
||||
(detect_container() == 0 && !unit_cgroup_delegate(u)))
|
||||
wait_for_exit = true;
|
||||
|
||||
if (c->send_sighup && k != KILL_KILL) {
|
||||
if (send_sighup) {
|
||||
set_free(pid_set);
|
||||
|
||||
pid_set = unit_pid_set(main_pid, control_pid);
|
||||
if (!pid_set)
|
||||
return -ENOMEM;
|
||||
|
||||
cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, SIGHUP, false, true, false, pid_set);
|
||||
cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path,
|
||||
SIGHUP,
|
||||
CGROUP_IGNORE_SELF,
|
||||
pid_set,
|
||||
NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ typedef struct UnitStatusMessageFormats UnitStatusMessageFormats;
|
||||
|
||||
typedef enum KillOperation {
|
||||
KILL_TERMINATE,
|
||||
KILL_TERMINATE_AND_LOG,
|
||||
KILL_KILL,
|
||||
KILL_ABORT,
|
||||
_KILL_OPERATION_MAX,
|
||||
|
||||
+14
-12
@@ -603,7 +603,6 @@ int session_start(Session *s) {
|
||||
|
||||
static int session_stop_scope(Session *s, bool force) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
char *job = NULL;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
@@ -611,22 +610,25 @@ static int session_stop_scope(Session *s, bool force) {
|
||||
if (!s->scope)
|
||||
return 0;
|
||||
|
||||
/* Let's always abandon the scope first. This tells systemd that we are not interested anymore, and everything
|
||||
* that is left in in the scope is "left-over". Informing systemd about this has the benefit that it will log
|
||||
* when killing any processes left after this point. */
|
||||
r = manager_abandon_scope(s->manager, s->scope, &error);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to abandon session scope, ignoring: %s", bus_error_message(&error, r));
|
||||
|
||||
/* Optionally, let's kill everything that's left now. */
|
||||
if (force || manager_shall_kill(s->manager, s->user->name)) {
|
||||
char *job = NULL;
|
||||
|
||||
r = manager_stop_unit(s->manager, s->scope, &error, &job);
|
||||
if (r < 0) {
|
||||
log_error("Failed to stop session scope: %s", bus_error_message(&error, r));
|
||||
return r;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to stop session scope: %s", bus_error_message(&error, r));
|
||||
|
||||
free(s->scope_job);
|
||||
s->scope_job = job;
|
||||
} else {
|
||||
r = manager_abandon_scope(s->manager, s->scope, &error);
|
||||
if (r < 0) {
|
||||
log_error("Failed to abandon session scope: %s", bus_error_message(&error, r));
|
||||
return r;
|
||||
}
|
||||
}
|
||||
} else
|
||||
s->scope_job = mfree(s->scope_job);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -60,16 +60,16 @@ int main(int argc, char*argv[]) {
|
||||
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a") > 0);
|
||||
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b") == 0);
|
||||
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, false, NULL) == 0);
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, false, NULL) > 0);
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, 0, NULL, NULL, NULL) == 0);
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, 0, NULL, NULL, NULL) > 0);
|
||||
|
||||
assert_se(cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", SYSTEMD_CGROUP_CONTROLLER, "/test-a", false, false) > 0);
|
||||
assert_se(cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0) > 0);
|
||||
|
||||
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a") == 0);
|
||||
assert_se(cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b") > 0);
|
||||
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, false, false, false, NULL) > 0);
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, false, false, false, NULL) == 0);
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-a", 0, 0, NULL, NULL, NULL) > 0);
|
||||
assert_se(cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, "/test-b", 0, 0, NULL, NULL, NULL) == 0);
|
||||
|
||||
cg_trim(SYSTEMD_CGROUP_CONTROLLER, "/", false);
|
||||
|
||||
|
||||
+1
-1
@@ -1256,7 +1256,7 @@ static int on_post(sd_event_source *s, void *userdata) {
|
||||
return r;
|
||||
} else if (manager->cgroup)
|
||||
/* cleanup possible left-over processes in our cgroup */
|
||||
cg_kill(SYSTEMD_CGROUP_CONTROLLER, manager->cgroup, SIGKILL, false, true, NULL);
|
||||
cg_kill(SYSTEMD_CGROUP_CONTROLLER, manager->cgroup, SIGKILL, CGROUP_IGNORE_SELF, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user