pwait: Add a SIGINFO handler

On SIGINFO, print a space-separated list or remaining processes to
standard error.

MFC after:	1 week
Sponsored by:	Klara, Inc.
Sponsored by:	NetApp, Inc.
Reviewed by:	kib, markj
Differential Revision:	https://reviews.freebsd.org/D58386
This commit is contained in:
Dag-Erling Smørgrav committed 2026-07-27 12:15:36 +02:00
1 parent c8f5e6819d
commit eddd8aa99c
2 files changed
+42 -7

No files matched your search

+13
View File
@@ -88,6 +88,18 @@ Print the exit status when each process terminates or
.Ql timeout
if the timer goes off earlier.
.El
.Pp
If
.Nm
receives
.Dv SIGINFO
(see the
.Sy status
argument for
.Xr stty 1 )
signal,
a space-separated list of processes still being waited on is printed
to the standard error output.
.Sh EXIT STATUS
The
.Nm
@@ -148,6 +160,7 @@ $ echo $?
.Xr kill 1 ,
.Xr pkill 1 ,
.Xr ps 1 ,
.Xr stty 1 ,
.Xr wait 1 ,
.Xr kqueue 2
.Sh NOTES
+29 -7
View File
@@ -87,7 +87,7 @@ main(int argc, char *argv[])
size_t sz;
long pid;
pid_t mypid;
int i, kq, n, ndone, nleft, notes, opt, pid_max, ret, status;
int i, kq, n, ndone, nev, nleft, notes, opt, pid_max, ret, status;
bool oflag, pflag, rflag, tflag, verbose;
oflag = false;
@@ -165,10 +165,10 @@ main(int argc, char *argv[])
if (sysctlbyname("kern.pid_max", &pid_max, &sz, NULL, 0) != 0) {
pid_max = 99999;
}
if ((e = malloc((argc + tflag) * sizeof(*e))) == NULL) {
if ((e = malloc((argc + 1 + tflag) * sizeof(*e))) == NULL) {
err(EX_OSERR, "malloc");
}
ndone = nleft = 0;
ndone = nev = nleft = 0;
mypid = getpid();
notes = rflag ? NOTE_REAP : NOTE_EXIT;
if (verbose)
@@ -208,18 +208,28 @@ main(int argc, char *argv[])
ndone++;
} else {
nleft++;
nev++;
}
}
/*
* Detect SIGINFO so we can print a status.
*/
EV_SET(e + nev, SIGINFO, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
if (kevent(kq, e + nev, 1, NULL, 0, NULL) == -1) {
err(EX_OSERR, "kevent");
}
nev++;
if ((ndone == 0 || !oflag) && nleft > 0 && tflag) {
/*
* Explicitly detect SIGALRM so that an exit status of 124
* can be returned rather than 142.
*/
EV_SET(e + nleft, SIGALRM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1) {
EV_SET(e + nev, SIGALRM, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
if (kevent(kq, e + nev, 1, NULL, 0, NULL) == -1) {
err(EX_OSERR, "kevent");
}
nev++;
/* Ignore SIGALRM to not interrupt kevent(2). */
signal(SIGALRM, SIG_IGN);
if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
@@ -227,13 +237,25 @@ main(int argc, char *argv[])
}
}
ret = EX_OK;
setvbuf(stderr, NULL, _IOLBF, 0);
while ((ndone == 0 || !oflag) && ret == EX_OK && nleft > 0) {
n = kevent(kq, NULL, 0, e, nleft + tflag, NULL);
n = kevent(kq, NULL, 0, e, nev, NULL);
if (n == -1) {
err(EX_OSERR, "kevent");
}
for (i = 0; i < n; i++) {
if (e[i].filter == EVFILT_SIGNAL) {
if (e[i].filter == EVFILT_SIGNAL &&
e[i].ident == SIGINFO) {
p = RB_MIN(pidtree, &pids);
fprintf(stderr, "%d", p->pid);
while ((p = RB_NEXT(pidtree, &pids, p)) != NULL) {
fprintf(stderr, " %d", p->pid);
}
fprintf(stderr, "\n");
continue;
}
if (e[i].filter == EVFILT_SIGNAL &&
e[i].ident == SIGALRM) {
if (verbose) {
printf("timeout\n");
}