The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=81ef00125056a68ca3bba1424d6cb13533bf474c

commit 81ef00125056a68ca3bba1424d6cb13533bf474c
Author:     Konstantin Belousov <k...@freebsd.org>
AuthorDate: 2025-06-09 03:20:16 +0000
Commit:     Konstantin Belousov <k...@freebsd.org>
CommitDate: 2025-06-09 23:52:34 +0000

    timeout(1): pass full 32bit error return code from the exited child
    
    Switch to use waitid(2) to receive siginfo_t with the complete error
    code from the exited process.
    
    Tested by:      pho
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D50752
---
 bin/timeout/timeout.c | 58 ++++++++++++++++++++++++++++++++-------------------
 1 file changed, 37 insertions(+), 21 deletions(-)

diff --git a/bin/timeout/timeout.c b/bin/timeout/timeout.c
index f47976aa27df..58a5797f3eaf 100644
--- a/bin/timeout/timeout.c
+++ b/bin/timeout/timeout.c
@@ -277,12 +277,25 @@ kill_self(int signo)
            sys_signame[signo], signo);
 }
 
+static void
+log_termination(const char *name, const siginfo_t *si)
+{
+       if (si->si_code == CLD_EXITED) {
+               logv("%s: pid=%d, exit=%d", name, si->si_pid, si->si_status);
+       } else if (si->si_code == CLD_DUMPED || si->si_code == CLD_KILLED) {
+               logv("%s: pid=%d, sig=%d", name, si->si_pid, si->si_status);
+       } else {
+               logv("%s: pid=%d, reason=%d, status=%d", si->si_pid,
+                   si->si_code, si->si_status);
+       }
+}
+
 int
 main(int argc, char **argv)
 {
-       int ch, status, sig;
+       int ch, sig;
        int pstat = 0;
-       pid_t pid, cpid;
+       pid_t pid;
        int pp[2], error;
        char c;
        double first_kill;
@@ -295,6 +308,7 @@ main(int argc, char **argv)
        sigset_t zeromask, allmask, oldmask;
        struct sigaction sa;
        struct procctl_reaper_status info;
+       siginfo_t si, child_si;
 
        const char optstr[] = "+fhk:ps:v";
        const struct option longopts[] = {
@@ -414,26 +428,27 @@ main(int argc, char **argv)
                if (sig_chld) {
                        sig_chld = 0;
 
-                       while ((cpid = waitpid(-1, &status, WNOHANG)) != 0) {
-                               if (cpid < 0) {
+                       for (;;) {
+                               memset(&si, 0, sizeof(si));
+                               error = waitid(P_ALL, -1, &si, WEXITED |
+                                   WNOHANG);
+                               if (error == -1) {
                                        if (errno != EINTR)
                                                break;
-                               } else if (cpid == pid) {
-                                       pstat = status;
+                               } else if (si.si_pid == pid) {
+                                       child_si = si;
                                        child_done = true;
-                                       logv("child terminated: pid=%d, "
-                                            "exit=%d, signal=%d",
-                                            (int)pid, WEXITSTATUS(status),
-                                            WTERMSIG(status));
-                               } else {
+                                       log_termination("child terminated",
+                                           &child_si);
+                               } else if (si.si_pid != 0) {
                                        /*
                                         * Collect grandchildren zombies.
                                         * Only effective if we're a reaper.
                                         */
-                                       logv("collected zombie: pid=%d, "
-                                            "exit=%d, signal=%d",
-                                            (int)cpid, WEXITSTATUS(status),
-                                            WTERMSIG(status));
+                                       log_termination("collected zombie",
+                                           &si);
+                               } else /* si.si_pid == 0 */ {
+                                       break;
                                }
                        }
                        if (child_done) {
@@ -482,13 +497,14 @@ main(int argc, char **argv)
 
        if (timedout && !preserve) {
                pstat = EXIT_TIMEOUT;
+       } else if (child_si.si_code == CLD_DUMPED ||
+           child_si.si_code == CLD_KILLED) {
+               kill_self(child_si.si_status);
+               /* NOTREACHED */
+       } else if (child_si.si_code == CLD_EXITED) {
+               pstat = child_si.si_status;
        } else {
-               if (WIFSIGNALED(pstat))
-                       kill_self(WTERMSIG(pstat));
-                       /* NOTREACHED */
-
-               if (WIFEXITED(pstat))
-                       pstat = WEXITSTATUS(pstat);
+               pstat = EXIT_FAILURE;
        }
 
        return (pstat);

Reply via email to