chiark / gitweb /
core: optionally send SIGHUP in addition to the configured kill signal
authorLennart Poettering <lennart@poettering.net>
Mon, 29 Jul 2013 23:54:59 +0000 (01:54 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 29 Jul 2013 23:54:59 +0000 (01:54 +0200)
This is useful to fake session ends for processes like shells.

13 files changed:
man/systemd.kill.xml
src/core/dbus-kill.c
src/core/dbus-kill.h
src/core/kill.c
src/core/kill.h
src/core/load-fragment-gperf.gperf.m4
src/core/unit.c
units/console-getty.service.m4.in
units/console-shell.service.m4.in
units/emergency.service.in
units/getty@.service.m4
units/rescue.service.m4.in
units/serial-getty@.service.m4

index 2a810e257f5be07668e08040a98067499a9783ad..517a891777658968b7b1426414f5a36d9f5832c0 100644 (file)
                                 <option>control-group</option>.</para>
 
                                 <para>Processes will first be
                                 <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
                                 then after a delay (configured via the
-                                <varname>TimeoutSec=</varname> option)
+                                <varname>TimeoutStopSec=</varname> option)
                                 processes still remain, the
                                 termination request is repeated with
                                 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
                                 option). See
                                 <citerefentry><refentrytitle>kill</refentrytitle><manvolnum>2</manvolnum></citerefentry>
                                 for more
                                 </para></listitem>
                         </varlistentry>
 
                                 </para></listitem>
                         </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
                         <varlistentry>
                                 <term><varname>SendSIGKILL=</varname></term>
                                 <listitem><para>Specifies whether to
                                 value. Defaults to "yes".
                                 </para></listitem>
                         </varlistentry>
                                 value. Defaults to "yes".
                                 </para></listitem>
                         </varlistentry>
+
                 </variablelist>
         </refsect1>
 
                 </variablelist>
         </refsect1>
 
index 165f63074ba6a02182342aa498883bcb8db0f58c..e970ea329c8700d25ab43c64c6de1bc480aa0d9c 100644 (file)
@@ -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) },
         { "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, }
 };
         { NULL, }
 };
index 238fbd36d650203df26080be04b9b00931889b0f..8c8bff592704f99d2b31bf61ddc2d034b39a74dc 100644 (file)
 #define BUS_KILL_CONTEXT_INTERFACE                                      \
         "  <property name=\"KillMode\" type=\"s\" access=\"read\"/>\n"  \
         "  <property name=\"KillSignal\" type=\"i\" access=\"read\"/>\n" \
 #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[];
 
 
 extern const BusProperty bus_kill_context_properties[];
 
index 0775653f73e6b23d21e401725b1a166201fdd36e..ea947c23ae04a3787e21b8377f5cd9fdf5c079d3 100644 (file)
@@ -29,6 +29,7 @@ void kill_context_init(KillContext *c) {
 
         c->kill_signal = SIGTERM;
         c->send_sigkill = true;
 
         c->kill_signal = SIGTERM;
         c->send_sigkill = true;
+        c->send_sighup = false;
 }
 
 void kill_context_dump(KillContext *c, FILE *f, const char *prefix) {
 }
 
 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"
         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, 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] = {
 }
 
 static const char* const kill_mode_table[_KILL_MODE_MAX] = {
index 71a0513e840f0d1be0d995db6f66a199c0ea8206..41773f07aeac18bd4c23f50dbf085229281c166d 100644 (file)
@@ -41,6 +41,7 @@ struct KillContext {
         KillMode kill_mode;
         int kill_signal;
         bool send_sigkill;
         KillMode kill_mode;
         int kill_signal;
         bool send_sigkill;
+        bool send_sighup;
 };
 
 typedef enum KillWho {
 };
 
 typedef enum KillWho {
index 0c337bca9caaf0891a783cfcb1c432d34d32e8e3..2b0106ffe2e5c21979fb785f01bed07649cc7681 100644 (file)
@@ -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)
 )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
 $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
index 0e9329f8c9b1e993ef67b3f6d103ac00a7dc35a7..b56be83a318684b2ef8626804b1cab69d3e0b247 100644 (file)
@@ -2542,6 +2542,34 @@ int unit_kill(Unit *u, KillWho w, int signo, DBusError *error) {
         return UNIT_VTABLE(u)->kill(u, w, signo, 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,
 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;
 
                 _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;
 
                 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;
                 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));
 
                         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;
                         wait_for_exit = !main_pid_alien;
+
+                        if (c->send_sighup)
+                                kill(main_pid, SIGHUP);
+                }
         }
 
         if (control_pid > 0) {
         }
 
         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));
                         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;
                         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;
 
         }
 
         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;
 
                 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));
                 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;
                         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;
         }
 
         return wait_for_exit;
index 0426050ee8df9bf3afc9f5be7cbcdd2482f76cb7..2fd9dd8478ababfc8748bace6a4abbcb3f2a6af0 100644 (file)
@@ -25,10 +25,7 @@ TTYReset=yes
 TTYVHangup=yes
 KillMode=process
 IgnoreSIGPIPE=no
 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
 
 [Install]
 WantedBy=getty.target
index dac2ac212bfddf9f7dc6baf3aad8797cd6514049..3f4904a0eeac882c90dfea9298bcb3dda9e77180 100644 (file)
@@ -25,10 +25,7 @@ StandardOutput=inherit
 StandardError=inherit
 KillMode=process
 IgnoreSIGPIPE=no
 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
 
 [Install]
 WantedBy=getty.target
index 442f0e0ee637adda8de664bfac7f125f5b23da06..94c090f654be34b42cf8014ce255dbad86ae0ca1 100644 (file)
@@ -25,7 +25,4 @@ StandardOutput=inherit
 StandardError=inherit
 KillMode=process
 IgnoreSIGPIPE=no
 StandardError=inherit
 KillMode=process
 IgnoreSIGPIPE=no
-
-# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
-# terminates cleanly.
-KillSignal=SIGHUP
+SendSIGHUP=yes
index 7853652009992e09eaa6c9ee00b1c21ac826a798..253da85f8e345c3a95883915f449ba2f3f3e831b 100644 (file)
@@ -38,14 +38,11 @@ TTYVHangup=yes
 TTYVTDisallocate=yes
 KillMode=process
 IgnoreSIGPIPE=no
 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=
 
 
 # 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
 [Install]
 WantedBy=getty.target
index 269797a12ebfb6bd3a910a45f4ec3d89cdfc0fba..552ef8981b5870c81bd2dc9652eba3c12652c55c 100644 (file)
@@ -25,7 +25,5 @@ StandardInput=tty-force
 StandardOutput=inherit
 StandardError=inherit
 KillMode=process
 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
index 5e16963e92b861e24a73b3b08a8027c1c03f1fdd..e32c6b7aff00d91cd748cf63710b3b21f100eb66 100644 (file)
@@ -32,7 +32,4 @@ TTYReset=yes
 TTYVHangup=yes
 KillMode=process
 IgnoreSIGPIPE=no
 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