summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2025-06-09 06:20:16 +0300
committerKonstantin Belousov <kib@FreeBSD.org>2025-06-10 02:52:34 +0300
commit81ef00125056a68ca3bba1424d6cb13533bf474c (patch)
treeddd40ceb1740dd8f3d7463626537fc88af1f2efe /bin
parentaa8cdb7cae7b7550d5cb81d85ee294c4f182f694 (diff)
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
Diffstat (limited to 'bin')
-rw-r--r--bin/timeout/timeout.c58
1 files 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);