chiark / gitweb /
shutdown: during final killing spree also send SIGHUP in addition to SIGTERM to deal...
authorLennart Poettering <lennart@poettering.net>
Mon, 25 Nov 2013 17:08:02 +0000 (18:08 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 25 Nov 2013 21:10:22 +0000 (22:10 +0100)
This makes shutdown a bit faster if debug-shell.service is enabled.

TODO
src/core/killall.c
src/core/killall.h
src/core/main.c
src/core/shutdown.c
src/shared/util.c

diff --git a/TODO b/TODO
index 9b898bb57dbba94dd8d1aaa09fdacdd6777976a5..d63e13e3189c81b60e59f05fdc09193666bb49fc 100644 (file)
--- a/TODO
+++ b/TODO
@@ -43,6 +43,8 @@ CGroup Rework Completion:
 
 Features:
 
+* general: get rid of readdir_r/dirent_storage stuff, it's unnecessary on Linux
+
 * add API to clone sd_bus_message objects
 
 * sd-bus: synthesized messages should get serial number (uint32_t) -1
index e3950501075e736230eb3fd970faff65f17b9283..a7828dc0477e8b6d5d3b2e3f6f17a9c53820904d 100644 (file)
@@ -145,7 +145,7 @@ static void wait_for_children(Set *pids, sigset_t *mask) {
         }
 }
 
-static int killall(int sig, Set *pids) {
+static int killall(int sig, Set *pids, bool send_sighup) {
         _cleanup_closedir_ DIR *dir = NULL;
         struct dirent *d;
 
@@ -178,12 +178,28 @@ static int killall(int sig, Set *pids) {
                                 set_put(pids, ULONG_TO_PTR((unsigned long) pid));
                 } else if (errno != ENOENT)
                         log_warning("Could not kill %d: %m", pid);
+
+                if (send_sighup) {
+                        /* Optionally, also send a SIGHUP signal, but
+                        only if the process has a controlling
+                        tty. This is useful to allow handling of
+                        shells which ignore SIGTERM but react to
+                        SIGHUP. We do not send this to processes that
+                        have no controlling TTY since we don't want to
+                        trigger reloads of daemon processes. Also we
+                        make sure to only send this after SIGTERM so
+                        that SIGTERM is always first in the queue. */
+
+
+                        if (get_ctty_devnr(pid, NULL) >= 0)
+                                kill(pid, SIGHUP);
+                }
         }
 
         return set_size(pids);
 }
 
-void broadcast_signal(int sig, bool wait_for_exit) {
+void broadcast_signal(int sig, bool send_sighup, bool wait_for_exit) {
         sigset_t mask, oldmask;
         Set *pids = NULL;
 
@@ -197,7 +213,7 @@ void broadcast_signal(int sig, bool wait_for_exit) {
         if (kill(-1, SIGSTOP) < 0 && errno != ESRCH)
                 log_warning("kill(-1, SIGSTOP) failed: %m");
 
-        killall(sig, pids);
+        killall(sig, pids, send_sighup);
 
         if (kill(-1, SIGCONT) < 0 && errno != ESRCH)
                 log_warning("kill(-1, SIGCONT) failed: %m");
index 95b110fae14b711f93b63ece506c4fb2c0c17c3a..bdb73e44becd3716b2245b47f8c8d623c041ae8f 100644 (file)
@@ -21,4 +21,4 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-void broadcast_signal(int sig, bool wait);
+void broadcast_signal(int sig, bool wait, bool send_sighup);
index bc92f65fd6c9d211029aa104ecb31ba05f383030..dbc98db84ab97886872286c309d00b03b02dce91 100644 (file)
@@ -1745,7 +1745,7 @@ finish:
                          * initrd, but don't wait for them, so that we
                          * can handle the SIGCHLD for them after
                          * deserializing. */
-                        broadcast_signal(SIGTERM, false);
+                        broadcast_signal(SIGTERM, false, true);
 
                         /* And switch root */
                         r = switch_root(switch_root_dir);
index bcf2eecf33ad0bd74d4e402907c61b58856f62ec..31129b7697edf01ae5de5787b7c5b75816fe4e64 100644 (file)
@@ -195,10 +195,10 @@ int main(int argc, char *argv[]) {
         mlockall(MCL_CURRENT|MCL_FUTURE);
 
         log_info("Sending SIGTERM to remaining processes...");
-        broadcast_signal(SIGTERM, true);
+        broadcast_signal(SIGTERM, true, true);
 
         log_info("Sending SIGKILL to remaining processes...");
-        broadcast_signal(SIGKILL, true);
+        broadcast_signal(SIGKILL, true, false);
 
         if (in_container) {
                 need_swapoff = false;
index 97c9497df671f3f87b3312473baa7369ad192d82..3a4d1965ae314788152999d7d518186744ad2601 100644 (file)
@@ -2525,10 +2525,8 @@ int get_ctty_devnr(pid_t pid, dev_t *d) {
         char line[LINE_MAX], *p;
         unsigned long ttynr;
         const char *fn;
-        int k;
 
         assert(pid >= 0);
-        assert(d);
 
         if (pid == 0)
                 fn = "/proc/self/stat";
@@ -2539,10 +2537,8 @@ int get_ctty_devnr(pid_t pid, dev_t *d) {
         if (!f)
                 return -errno;
 
-        if (!fgets(line, sizeof(line), f)) {
-                k = feof(f) ? -EIO : -errno;
-                return k;
-        }
+        if (!fgets(line, sizeof(line), f))
+                return feof(f) ? -EIO : -errno;
 
         p = strrchr(line, ')');
         if (!p)
@@ -2562,7 +2558,9 @@ int get_ctty_devnr(pid_t pid, dev_t *d) {
         if (major(ttynr) == 0 && minor(ttynr) == 0)
                 return -ENOENT;
 
-        *d = (dev_t) ttynr;
+        if (d)
+                *d = (dev_t) ttynr;
+
         return 0;
 }