]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/killall: Propagate errors and return the number of process left
authorBenjamin Robin <dev@benjarobin.fr>
Wed, 3 Apr 2019 17:20:12 +0000 (19:20 +0200)
committerBenjamin Robin <dev@benjarobin.fr>
Mon, 8 Apr 2019 17:41:16 +0000 (19:41 +0200)
src/core/killall.c
src/core/killall.h

index f0ce9965567303d08c75b824575be605d3a164de..7ff9e3a24606bb166c2a66c1efa95c30d9ae5f41 100644 (file)
@@ -77,13 +77,16 @@ static bool ignore_proc(pid_t pid, bool warn_rootfs) {
         return true;
 }
 
-static void wait_for_children(Set *pids, sigset_t *mask, usec_t timeout) {
+static int wait_for_children(Set *pids, sigset_t *mask, usec_t timeout) {
         usec_t until;
 
         assert(mask);
 
+        /* Return the number of children remaining in the pids set: That correspond to the number
+         * of processes still "alive" after the timeout */
+
         if (set_isempty(pids))
-                return;
+                return 0;
 
         until = now(CLOCK_MONOTONIC) + timeout;
         for (;;) {
@@ -107,8 +110,7 @@ static void wait_for_children(Set *pids, sigset_t *mask, usec_t timeout) {
                                 if (errno == ECHILD)
                                         break;
 
-                                log_error_errno(errno, "waitpid() failed: %m");
-                                return;
+                                return log_error_errno(errno, "waitpid() failed: %m");
                         }
 
                         (void) set_remove(pids, PID_TO_PTR(pid));
@@ -130,20 +132,18 @@ static void wait_for_children(Set *pids, sigset_t *mask, usec_t timeout) {
                 }
 
                 if (set_isempty(pids))
-                        return;
+                        return 0;
 
                 n = now(CLOCK_MONOTONIC);
                 if (n >= until)
-                        return;
+                        return set_size(pids);
 
                 timespec_store(&ts, until - n);
                 k = sigtimedwait(mask, NULL, &ts);
                 if (k != SIGCHLD) {
 
-                        if (k < 0 && errno != EAGAIN) {
-                                log_error_errno(errno, "sigtimedwait() failed: %m");
-                                return;
-                        }
+                        if (k < 0 && errno != EAGAIN)
+                                return log_error_errno(errno, "sigtimedwait() failed: %m");
 
                         if (k >= 0)
                                 log_warning("sigtimedwait() returned unexpected signal.");
@@ -154,10 +154,14 @@ static void wait_for_children(Set *pids, sigset_t *mask, usec_t timeout) {
 static int killall(int sig, Set *pids, bool send_sighup) {
         _cleanup_closedir_ DIR *dir = NULL;
         struct dirent *d;
+        int n_killed = 0;
+
+        /* Send the specified signal to all remaining processes, if not excluded by ignore_proc().
+         * Returns the number of processes to which the specified signal was sent */
 
         dir = opendir("/proc");
         if (!dir)
-                return -errno;
+                return log_warning_errno(errno, "opendir(/proc) failed: %m");
 
         FOREACH_DIRENT_ALL(d, dir, break) {
                 pid_t pid;
@@ -180,6 +184,7 @@ static int killall(int sig, Set *pids, bool send_sighup) {
                 }
 
                 if (kill(pid, sig) >= 0) {
+                        n_killed++;
                         if (pids) {
                                 r = set_put(pids, PID_TO_PTR(pid));
                                 if (r < 0)
@@ -205,10 +210,11 @@ static int killall(int sig, Set *pids, bool send_sighup) {
                 }
         }
 
-        return set_size(pids);
+        return n_killed;
 }
 
-void broadcast_signal(int sig, bool wait_for_exit, bool send_sighup, usec_t timeout) {
+int broadcast_signal(int sig, bool wait_for_exit, bool send_sighup, usec_t timeout) {
+        int n_children_left;
         sigset_t mask, oldmask;
         _cleanup_set_free_ Set *pids = NULL;
 
@@ -222,13 +228,15 @@ void broadcast_signal(int sig, bool wait_for_exit, bool send_sighup, usec_t time
         if (kill(-1, SIGSTOP) < 0 && errno != ESRCH)
                 log_warning_errno(errno, "kill(-1, SIGSTOP) failed: %m");
 
-        killall(sig, pids, send_sighup);
+        n_children_left = killall(sig, pids, send_sighup);
 
         if (kill(-1, SIGCONT) < 0 && errno != ESRCH)
                 log_warning_errno(errno, "kill(-1, SIGCONT) failed: %m");
 
-        if (wait_for_exit)
-                wait_for_children(pids, &mask, timeout);
+        if (wait_for_exit && n_children_left > 0)
+                n_children_left = wait_for_children(pids, &mask, timeout);
 
         assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) == 0);
+
+        return n_children_left;
 }
index cbd202651ce76d0236834c7707e5238c80dcc613..08ae28d073f4d16317136ed499c7ea1bd0a37fde 100644 (file)
@@ -3,4 +3,4 @@
 
 #include "time-util.h"
 
-void broadcast_signal(int sig, bool wait_for_exit, bool send_sighup, usec_t timeout);
+int broadcast_signal(int sig, bool wait_for_exit, bool send_sighup, usec_t timeout);