From: Benjamin Robin Date: Wed, 3 Apr 2019 17:20:12 +0000 (+0200) Subject: core/killall: Propagate errors and return the number of process left X-Git-Tag: v243-rc1~569^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a012f9f7cfc50c88cc6e9630be4aaa829789de02;p=thirdparty%2Fsystemd.git core/killall: Propagate errors and return the number of process left --- diff --git a/src/core/killall.c b/src/core/killall.c index f0ce9965567..7ff9e3a2460 100644 --- a/src/core/killall.c +++ b/src/core/killall.c @@ -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; } diff --git a/src/core/killall.h b/src/core/killall.h index cbd202651ce..08ae28d073f 100644 --- a/src/core/killall.h +++ b/src/core/killall.h @@ -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);