core/killall: Propagate errors and return the number of process left

This commit is contained in:
Benjamin Robin
2019-04-08 19:41:16 +02:00
parent b3e8032bb4
commit a012f9f7cf
2 changed files with 25 additions and 17 deletions
+24 -16
View 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;
}
+1 -1
View 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);