aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2024-03-18 08:44:39 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2024-03-27 08:27:52 +0000
commit1d2a587ef9f8310da6a9203bd1fff43d61ca66f7 (patch)
tree61825f532fbbac4977d97e3c8f5029bc0ce6ebc5
parent285f941478d83b04fbbc53ee4003705cd41199b3 (diff)
downloadsrc-1d2a587ef9f8310da6a9203bd1fff43d61ca66f7.tar.gz
src-1d2a587ef9f8310da6a9203bd1fff43d61ca66f7.zip
daemon(8): handle case of waitpid() returning without exited child
PR: 277764 (cherry picked from commit 8eaa6be80d6aef6a118fa854a860bfdaeb7ed753)
-rw-r--r--usr.sbin/daemon/daemon.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/usr.sbin/daemon/daemon.c b/usr.sbin/daemon/daemon.c
index 65e6bb7ca190..da8e4895e19b 100644
--- a/usr.sbin/daemon/daemon.c
+++ b/usr.sbin/daemon/daemon.c
@@ -743,18 +743,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;