index | | raw e-mail
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
(cherry picked from commit eddd8aa99ca84c85faea5761af800b5b089d6ba1)
---
bin/pwait/pwait.1 | 13 +++++++++++++
bin/pwait/pwait.c | 36 +++++++++++++++++++++++++++++-------
2 files changed, 42 insertions(+), 7 deletions(-)
diff --git a/bin/pwait/pwait.1 b/bin/pwait/pwait.1
index a80c04a1e688..738f11aa5468 100644
--- a/bin/pwait/pwait.1
+++ b/bin/pwait/pwait.1
@@ -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
diff --git a/bin/pwait/pwait.c b/bin/pwait/pwait.c
index 385278dbc991..7a08425700e6 100644
--- a/bin/pwait/pwait.c
+++ b/bin/pwait/pwait.c
@@ -86,7 +86,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;
@@ -164,10 +164,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)
@@ -207,18 +207,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) {
@@ -226,13 +236,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");
}
home |
help
