diff options
author | Lennart Poettering <lennart@poettering.net> | 2013-07-30 01:54:59 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2013-07-30 01:54:59 +0200 |
commit | 82659fd7571bda0f3dce9755b89a23c411d53dda (patch) | |
tree | 00ea49ad7be58cc9630f249ad8c7def09939daf7 /src/core | |
parent | 5a4555ba6bc8ea086823fb71cb1cb92d4ec087a2 (diff) |
core: optionally send SIGHUP in addition to the configured kill signal
This is useful to fake session ends for processes like shells.
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/dbus-kill.c | 1 | ||||
-rw-r--r-- | src/core/dbus-kill.h | 6 | ||||
-rw-r--r-- | src/core/kill.c | 7 | ||||
-rw-r--r-- | src/core/kill.h | 1 | ||||
-rw-r--r-- | src/core/load-fragment-gperf.gperf.m4 | 1 | ||||
-rw-r--r-- | src/core/unit.c | 84 |
6 files changed, 63 insertions, 37 deletions
diff --git a/src/core/dbus-kill.c b/src/core/dbus-kill.c index 165f63074b..e970ea329c 100644 --- a/src/core/dbus-kill.c +++ b/src/core/dbus-kill.c @@ -31,5 +31,6 @@ const BusProperty bus_kill_context_properties[] = { { "KillMode", bus_kill_append_mode, "s", offsetof(KillContext, kill_mode) }, { "KillSignal", bus_property_append_int, "i", offsetof(KillContext, kill_signal) }, { "SendSIGKILL", bus_property_append_bool, "b", offsetof(KillContext, send_sigkill) }, + { "SendSIGHUP", bus_property_append_bool, "b", offsetof(KillContext, send_sighup) }, { NULL, } }; diff --git a/src/core/dbus-kill.h b/src/core/dbus-kill.h index 238fbd36d6..8c8bff5927 100644 --- a/src/core/dbus-kill.h +++ b/src/core/dbus-kill.h @@ -29,10 +29,8 @@ #define BUS_KILL_CONTEXT_INTERFACE \ " <property name=\"KillMode\" type=\"s\" access=\"read\"/>\n" \ " <property name=\"KillSignal\" type=\"i\" access=\"read\"/>\n" \ - " <property name=\"SendSIGKILL\" type=\"b\" access=\"read\"/>\n" - -#define BUS_KILL_COMMAND_INTERFACE(name) \ - " <property name=\"" name "\" type=\"a(sasbttuii)\" access=\"read\"/>\n" + " <property name=\"SendSIGKILL\" type=\"b\" access=\"read\"/>\n" \ + " <property name=\"SendSIGHUP\" type=\"b\" access=\"read\"/>\n" extern const BusProperty bus_kill_context_properties[]; diff --git a/src/core/kill.c b/src/core/kill.c index 0775653f73..ea947c23ae 100644 --- a/src/core/kill.c +++ b/src/core/kill.c @@ -29,6 +29,7 @@ void kill_context_init(KillContext *c) { c->kill_signal = SIGTERM; c->send_sigkill = true; + c->send_sighup = false; } void kill_context_dump(KillContext *c, FILE *f, const char *prefix) { @@ -40,10 +41,12 @@ void kill_context_dump(KillContext *c, FILE *f, const char *prefix) { fprintf(f, "%sKillMode: %s\n" "%sKillSignal: SIG%s\n" - "%sSendSIGKILL: %s\n", + "%sSendSIGKILL: %s\n" + "%sSendSIGHUP: %s\n", prefix, kill_mode_to_string(c->kill_mode), prefix, signal_to_string(c->kill_signal), - prefix, yes_no(c->send_sigkill)); + prefix, yes_no(c->send_sigkill), + prefix, yes_no(c->send_sighup)); } static const char* const kill_mode_table[_KILL_MODE_MAX] = { diff --git a/src/core/kill.h b/src/core/kill.h index 71a0513e84..41773f07ae 100644 --- a/src/core/kill.h +++ b/src/core/kill.h @@ -41,6 +41,7 @@ struct KillContext { KillMode kill_mode; int kill_signal; bool send_sigkill; + bool send_sighup; }; typedef enum KillWho { diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 0c337bca9c..2b0106ffe2 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -79,6 +79,7 @@ $1.UtmpIdentifier, config_parse_unit_string_printf, 0, )m4_dnl m4_define(`KILL_CONTEXT_CONFIG_ITEMS', `$1.SendSIGKILL, config_parse_bool, 0, offsetof($1, kill_context.send_sigkill) +$1.SendSIGHUP, config_parse_bool, 0, offsetof($1, kill_context.send_sighup) $1.KillMode, config_parse_kill_mode, 0, offsetof($1, kill_context.kill_mode) $1.KillSignal, config_parse_kill_signal, 0, offsetof($1, kill_context.kill_signal)' )m4_dnl diff --git a/src/core/unit.c b/src/core/unit.c index 0e9329f8c9..b56be83a31 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -2542,6 +2542,34 @@ int unit_kill(Unit *u, KillWho w, int signo, DBusError *error) { return UNIT_VTABLE(u)->kill(u, w, signo, error); } +static Set *unit_pid_set(pid_t main_pid, pid_t control_pid) { + Set *pid_set; + int r; + + pid_set = set_new(trivial_hash_func, trivial_compare_func); + if (!pid_set) + return NULL; + + /* Exclude the main/control pids from being killed via the cgroup */ + if (main_pid > 0) { + r = set_put(pid_set, LONG_TO_PTR(main_pid)); + if (r < 0) + goto fail; + } + + if (control_pid > 0) { + r = set_put(pid_set, LONG_TO_PTR(control_pid)); + if (r < 0) + goto fail; + } + + return pid_set; + +fail: + set_free(pid_set); + return NULL; +} + int unit_kill_common( Unit *u, KillWho who, @@ -2582,23 +2610,11 @@ int unit_kill_common( _cleanup_set_free_ Set *pid_set = NULL; int q; - pid_set = set_new(trivial_hash_func, trivial_compare_func); + /* Exclude the main/control pids from being killed via the cgroup */ + pid_set = unit_pid_set(main_pid, control_pid); if (!pid_set) return -ENOMEM; - /* Exclude the control/main pid from being killed via the cgroup */ - if (control_pid > 0) { - q = set_put(pid_set, LONG_TO_PTR(control_pid)); - if (q < 0) - return q; - } - - if (main_pid > 0) { - q = set_put(pid_set, LONG_TO_PTR(main_pid)); - if (q < 0) - return q; - } - q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, true, false, pid_set); if (q < 0 && q != -EAGAIN && q != -ESRCH && q != -ENOENT) r = q; @@ -2949,8 +2965,12 @@ int unit_kill_context( log_warning_unit(u->id, "Failed to kill main process %li (%s): %s", (long) main_pid, strna(comm), strerror(-r)); - } else + } else { wait_for_exit = !main_pid_alien; + + if (c->send_sighup) + kill(main_pid, SIGHUP); + } } if (control_pid > 0) { @@ -2963,36 +2983,38 @@ int unit_kill_context( log_warning_unit(u->id, "Failed to kill control process %li (%s): %s", (long) control_pid, strna(comm), strerror(-r)); - } else + } else { wait_for_exit = true; + + if (c->send_sighup) + kill(control_pid, SIGHUP); + } } if (c->kill_mode == KILL_CONTROL_GROUP && u->cgroup_path) { _cleanup_set_free_ Set *pid_set = NULL; - pid_set = set_new(trivial_hash_func, trivial_compare_func); + /* Exclude the main/control pids from being killed via the cgroup */ + pid_set = unit_pid_set(main_pid, control_pid); if (!pid_set) return -ENOMEM; - /* Exclude the main/control pids from being killed via the cgroup */ - if (main_pid > 0) { - r = set_put(pid_set, LONG_TO_PTR(main_pid)); - if (r < 0) - return r; - } - - if (control_pid > 0) { - r = set_put(pid_set, LONG_TO_PTR(control_pid)); - if (r < 0) - return r; - } - r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, sig, true, true, false, pid_set); if (r < 0) { if (r != -EAGAIN && r != -ESRCH && r != -ENOENT) log_warning_unit(u->id, "Failed to kill control group: %s", strerror(-r)); - } else if (r > 0) + } else if (r > 0) { wait_for_exit = true; + if (c->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, true, true, false, pid_set); + } + } } return wait_for_exit; |