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 | |
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.
-rw-r--r-- | man/systemd.kill.xml | 34 | ||||
-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 | ||||
-rw-r--r-- | units/console-getty.service.m4.in | 5 | ||||
-rw-r--r-- | units/console-shell.service.m4.in | 5 | ||||
-rw-r--r-- | units/emergency.service.in | 5 | ||||
-rw-r--r-- | units/getty@.service.m4 | 5 | ||||
-rw-r--r-- | units/rescue.service.m4.in | 6 | ||||
-rw-r--r-- | units/serial-getty@.service.m4 | 5 |
13 files changed, 97 insertions, 68 deletions
diff --git a/man/systemd.kill.xml b/man/systemd.kill.xml index 2a810e257f..517a891777 100644 --- a/man/systemd.kill.xml +++ b/man/systemd.kill.xml @@ -115,16 +115,21 @@ <option>control-group</option>.</para> <para>Processes will first be - terminated via <constant>SIGTERM</constant> (unless the - signal to send is changed via - <varname>KillSignal=</varname>). If + terminated via + <constant>SIGTERM</constant> (unless + the signal to send is changed via + <varname>KillSignal=</varname>). Optionally, + this is immediately followed by a + <constant>SIGHUP</constant> (if + enabled with + <varname>SendSIGHUP=</varname>). If then after a delay (configured via the - <varname>TimeoutSec=</varname> option) + <varname>TimeoutStopSec=</varname> option) processes still remain, the termination request is repeated with - the <constant>SIGKILL</constant> signal (unless this is - disabled via the - <varname>SendSIGKILL=</varname> + the <constant>SIGKILL</constant> + signal (unless this is disabled via + the <varname>SendSIGKILL=</varname> option). See <citerefentry><refentrytitle>kill</refentrytitle><manvolnum>2</manvolnum></citerefentry> for more @@ -140,6 +145,20 @@ </varlistentry> <varlistentry> + <term><varname>SendSIGHUP=</varname></term> + <listitem><para>Specifies whether to + send <constant>SIGHUP</constant> to + remaining processes immediately after + sending the signal configured with + <varname>KillSignal=</varname>. This + is useful to indicate to shells and + shell-like programs that their + connection has been severed. Takes a + boolean value. Defaults to "no". + </para></listitem> + </varlistentry> + + <varlistentry> <term><varname>SendSIGKILL=</varname></term> <listitem><para>Specifies whether to send <constant>SIGKILL</constant> to remaining processes @@ -149,6 +168,7 @@ value. Defaults to "yes". </para></listitem> </varlistentry> + </variablelist> </refsect1> 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; diff --git a/units/console-getty.service.m4.in b/units/console-getty.service.m4.in index 0426050ee8..2fd9dd8478 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 dac2ac212b..3f4904a0ee 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 442f0e0ee6..94c090f654 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 7853652009..253da85f8e 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 269797a12e..552ef8981b 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 5e16963e92..e32c6b7aff 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 |