From: Lennart Poettering Date: Mon, 29 Jul 2013 23:54:59 +0000 (+0200) Subject: core: optionally send SIGHUP in addition to the configured kill signal X-Git-Tag: v207~219 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=82659fd7571bda0f3dce9755b89a23c411d53dda core: optionally send SIGHUP in addition to the configured kill signal This is useful to fake session ends for processes like shells. --- diff --git a/man/systemd.kill.xml b/man/systemd.kill.xml index 2a810e257..517a89177 100644 --- a/man/systemd.kill.xml +++ b/man/systemd.kill.xml @@ -115,16 +115,21 @@ . Processes will first be - terminated via SIGTERM (unless the - signal to send is changed via - KillSignal=). If + terminated via + SIGTERM (unless + the signal to send is changed via + KillSignal=). Optionally, + this is immediately followed by a + SIGHUP (if + enabled with + SendSIGHUP=). If then after a delay (configured via the - TimeoutSec= option) + TimeoutStopSec= option) processes still remain, the termination request is repeated with - the SIGKILL signal (unless this is - disabled via the - SendSIGKILL= + the SIGKILL + signal (unless this is disabled via + the SendSIGKILL= option). See kill2 for more @@ -139,6 +144,20 @@ + + SendSIGHUP= + Specifies whether to + send SIGHUP to + remaining processes immediately after + sending the signal configured with + KillSignal=. This + is useful to indicate to shells and + shell-like programs that their + connection has been severed. Takes a + boolean value. Defaults to "no". + + + SendSIGKILL= Specifies whether to @@ -149,6 +168,7 @@ value. Defaults to "yes". + diff --git a/src/core/dbus-kill.c b/src/core/dbus-kill.c index 165f63074..e970ea329 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 238fbd36d..8c8bff592 100644 --- a/src/core/dbus-kill.h +++ b/src/core/dbus-kill.h @@ -29,10 +29,8 @@ #define BUS_KILL_CONTEXT_INTERFACE \ " \n" \ " \n" \ - " \n" - -#define BUS_KILL_COMMAND_INTERFACE(name) \ - " \n" + " \n" \ + " \n" extern const BusProperty bus_kill_context_properties[]; diff --git a/src/core/kill.c b/src/core/kill.c index 0775653f7..ea947c23a 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 71a0513e8..41773f07a 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 0c337bca9..2b0106ffe 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 0e9329f8c..b56be83a3 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; diff --git a/units/console-getty.service.m4.in b/units/console-getty.service.m4.in index 0426050ee..2fd9dd847 100644 --- a/units/console-getty.service.m4.in +++ b/units/console-getty.service.m4.in @@ -25,10 +25,7 @@ TTYReset=yes TTYVHangup=yes KillMode=process IgnoreSIGPIPE=no - -# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash -# terminates cleanly. -KillSignal=SIGHUP +SendSIGHUP=yes [Install] WantedBy=getty.target diff --git a/units/console-shell.service.m4.in b/units/console-shell.service.m4.in index dac2ac212..3f4904a0e 100644 --- a/units/console-shell.service.m4.in +++ b/units/console-shell.service.m4.in @@ -25,10 +25,7 @@ StandardOutput=inherit StandardError=inherit KillMode=process IgnoreSIGPIPE=no - -# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash -# terminates cleanly. -KillSignal=SIGHUP +SendSIGHUP=yes [Install] WantedBy=getty.target diff --git a/units/emergency.service.in b/units/emergency.service.in index 442f0e0ee..94c090f65 100644 --- a/units/emergency.service.in +++ b/units/emergency.service.in @@ -25,7 +25,4 @@ StandardOutput=inherit StandardError=inherit KillMode=process IgnoreSIGPIPE=no - -# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash -# terminates cleanly. -KillSignal=SIGHUP +SendSIGHUP=yes diff --git a/units/getty@.service.m4 b/units/getty@.service.m4 index 785365200..253da85f8 100644 --- a/units/getty@.service.m4 +++ b/units/getty@.service.m4 @@ -38,14 +38,11 @@ TTYVHangup=yes TTYVTDisallocate=yes KillMode=process IgnoreSIGPIPE=no +SendSIGHUP=yes # Unset locale for the console getty since the console has problems # displaying some internationalized messages. Environment=LANG= LANGUAGE= LC_CTYPE= LC_NUMERIC= LC_TIME= LC_COLLATE= LC_MONETARY= LC_MESSAGES= LC_PAPER= LC_NAME= LC_ADDRESS= LC_TELEPHONE= LC_MEASUREMENT= LC_IDENTIFICATION= -# Some login implementations ignore SIGTERM, so we send SIGHUP -# instead, to ensure that login terminates cleanly. -KillSignal=SIGHUP - [Install] WantedBy=getty.target diff --git a/units/rescue.service.m4.in b/units/rescue.service.m4.in index 269797a12..552ef8981 100644 --- a/units/rescue.service.m4.in +++ b/units/rescue.service.m4.in @@ -25,7 +25,5 @@ StandardInput=tty-force StandardOutput=inherit StandardError=inherit KillMode=process - -# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash -# terminates cleanly. -KillSignal=SIGHUP +IgnoreSIGPIPE=no +SendSIGHUP=yes diff --git a/units/serial-getty@.service.m4 b/units/serial-getty@.service.m4 index 5e16963e9..e32c6b7af 100644 --- a/units/serial-getty@.service.m4 +++ b/units/serial-getty@.service.m4 @@ -32,7 +32,4 @@ TTYReset=yes TTYVHangup=yes KillMode=process IgnoreSIGPIPE=no - -# Some login implementations ignore SIGTERM, so we send SIGHUP -# instead, to ensure that login terminates cleanly. -KillSignal=SIGHUP +SendSIGHUP=yes