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
This commit is contained in:
Konstantin Belousov 2024-03-18 10:44:39 +02:00
parent e07d37c705
commit 8eaa6be80d

View file

@ -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;