diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2024-03-18 08:44:39 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2024-03-20 01:07:00 +0000 |
commit | 8eaa6be80d6aef6a118fa854a860bfdaeb7ed753 (patch) | |
tree | 713e76b78d9fdd2d65365882a30c2d7abf77e05c | |
parent | e07d37c7056a549ce1ed5dd0dfdbeadfe1b82605 (diff) | |
download | src-8eaa6be80d6aef6a118fa854a860bfdaeb7ed753.tar.gz src-8eaa6be80d6aef6a118fa854a860bfdaeb7ed753.zip |
daemon(8): handle case of waitpid() returning without exited child
Not checking for either WIFEXITED(status) or zero result results in
never finishing the loop.
PR: 277764
Reviewed by: kevans (previous version)
Discussed with: Daniel Tameling
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D44401
-rw-r--r-- | usr.sbin/daemon/daemon.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/usr.sbin/daemon/daemon.c b/usr.sbin/daemon/daemon.c index 6cde194cf16e..bce215af75d1 100644 --- a/usr.sbin/daemon/daemon.c +++ b/usr.sbin/daemon/daemon.c @@ -755,18 +755,22 @@ daemon_terminate(struct daemon_state *state) } /* - * Returns true if SIGCHILD came from state->pid - * This function could hang if SIGCHILD was emittied for a reason other than - * child dying (e.g., ptrace attach). + * Returns true if SIGCHILD came from state->pid due to its exit. */ static bool daemon_is_child_dead(struct daemon_state *state) { + int status; + for (;;) { - int who = waitpid(-1, NULL, WNOHANG); - if (state->pid == who) { + int who = waitpid(-1, &status, WNOHANG); + if (state->pid == who && (WIFEXITED(status) || + WIFSIGNALED(status))) { return true; } + if (who == 0) { + return false; + } if (who == -1 && errno != EINTR) { warn("waitpid"); return false; |