summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2013-07-30 01:54:59 +0200
committerLennart Poettering <lennart@poettering.net>2013-07-30 01:54:59 +0200
commit82659fd7571bda0f3dce9755b89a23c411d53dda (patch)
tree00ea49ad7be58cc9630f249ad8c7def09939daf7
parent5a4555ba6bc8ea086823fb71cb1cb92d4ec087a2 (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.xml34
-rw-r--r--src/core/dbus-kill.c1
-rw-r--r--src/core/dbus-kill.h6
-rw-r--r--src/core/kill.c7
-rw-r--r--src/core/kill.h1
-rw-r--r--src/core/load-fragment-gperf.gperf.m41
-rw-r--r--src/core/unit.c84
-rw-r--r--units/console-getty.service.m4.in5
-rw-r--r--units/console-shell.service.m4.in5
-rw-r--r--units/emergency.service.in5
-rw-r--r--units/getty@.service.m45
-rw-r--r--units/rescue.service.m4.in6
-rw-r--r--units/serial-getty@.service.m45
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