diff options
author | Martin Pitt <martin.pitt@ubuntu.com> | 2016-07-22 09:18:30 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-22 09:18:30 +0200 |
commit | bf3dd08a81f7500973d8a4add8c73a0856ae5f7d (patch) | |
tree | 0610e6bcaa4aaf00acbe4859e4b7253bf8040d03 /src/core | |
parent | 5c3c778014f4c59dd97f31ca5ab2e7374f08bbf6 (diff) | |
parent | 756ed0e238b7243c2e4616083e838d90de6e33ed (diff) |
Merge pull request #3762 from poettering/sigkill-log
log about all processes we forcibly kill
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/cgroup.c | 2 | ||||
-rw-r--r-- | src/core/dbus-scope.c | 2 | ||||
-rw-r--r-- | src/core/scope.c | 16 | ||||
-rw-r--r-- | src/core/scope.h | 1 | ||||
-rw-r--r-- | src/core/service.c | 2 | ||||
-rw-r--r-- | src/core/unit.c | 98 | ||||
-rw-r--r-- | src/core/unit.h | 1 |
7 files changed, 93 insertions, 29 deletions
diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 94d1161605..8b0f11ed50 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -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"); diff --git a/src/core/dbus-scope.c b/src/core/dbus-scope.c index f557eedfc3..1abaf9f658 100644 --- a/src/core/dbus-scope.c +++ b/src/core/dbus-scope.c @@ -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); } diff --git a/src/core/scope.c b/src/core/scope.c index decd1a1f3f..b45e238974 100644 --- a/src/core/scope.c +++ b/src/core/scope.c @@ -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, diff --git a/src/core/scope.h b/src/core/scope.h index 713b8b9f02..eaf8e8b447 100644 --- a/src/core/scope.h +++ b/src/core/scope.h @@ -45,6 +45,7 @@ struct Scope { usec_t timeout_stop_usec; char *controller; + bool was_abandoned; sd_event_source *timer_event_source; }; diff --git a/src/core/service.c b/src/core/service.c index 13de671700..afb198507b 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -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) { diff --git a/src/core/unit.c b/src/core/unit.c index fdf7ce3af3..4934a0e56f 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -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); } } } diff --git a/src/core/unit.h b/src/core/unit.h index c41011ed9d..1eabfa51e2 100644 --- a/src/core/unit.h +++ b/src/core/unit.h @@ -36,6 +36,7 @@ typedef struct UnitStatusMessageFormats UnitStatusMessageFormats; typedef enum KillOperation { KILL_TERMINATE, + KILL_TERMINATE_AND_LOG, KILL_KILL, KILL_ABORT, _KILL_OPERATION_MAX, |