Skip site navigation (1)Skip section navigation (2)



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