Index: head/bin/pwait/pwait.c =================================================================== --- head/bin/pwait/pwait.c (revision 357139) +++ head/bin/pwait/pwait.c (revision 357140) @@ -1,195 +1,195 @@ /*- * Copyright (c) 2004-2009, Jilles Tjoelker * All rights reserved. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the * following conditions are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or * other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include static void usage(void) { errx(EX_USAGE, "usage: pwait [-t timeout] [-v] pid ..."); } /* * pwait - wait for processes to terminate */ int main(int argc, char *argv[]) { struct itimerval itv; int kq; struct kevent *e; int tflag, verbose; int opt, nleft, n, i, status; long pid; char *s, *end; double timeout; tflag = verbose = 0; memset(&itv, 0, sizeof(itv)); while ((opt = getopt(argc, argv, "t:v")) != -1) { switch (opt) { case 't': tflag = 1; errno = 0; timeout = strtod(optarg, &end); if (end == optarg || errno == ERANGE || timeout < 0) errx(EX_DATAERR, "timeout value"); switch(*end) { case 0: case 's': break; case 'h': timeout *= 60; /* FALLTHROUGH */ case 'm': timeout *= 60; break; default: errx(EX_DATAERR, "timeout unit"); } if (timeout > 100000000L) errx(EX_DATAERR, "timeout value"); itv.it_value.tv_sec = (time_t)timeout; timeout -= (time_t)timeout; itv.it_value.tv_usec = (suseconds_t)(timeout * 1000000UL); break; case 'v': verbose = 1; break; default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc == 0) usage(); kq = kqueue(); if (kq == -1) err(EX_OSERR, "kqueue"); e = malloc((argc + tflag) * sizeof(struct kevent)); if (e == NULL) err(EX_OSERR, "malloc"); nleft = 0; for (n = 0; n < argc; n++) { s = argv[n]; if (!strncmp(s, "/proc/", 6)) /* Undocumented Solaris compat */ s += 6; errno = 0; pid = strtol(s, &end, 10); if (pid < 0 || *end != '\0' || errno != 0) { warnx("%s: bad process id", s); continue; } for (i = 0; i < nleft; i++) { if (e[i].ident == (uintptr_t)pid) break; } if (i < nleft) { /* Duplicate. */ continue; } EV_SET(e + nleft, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL); if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1) warn("%ld", pid); else nleft++; } - if (tflag) { + if (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) err(EX_OSERR, "kevent"); /* Ignore SIGALRM to not interrupt kevent(2). */ signal(SIGALRM, SIG_IGN); if (setitimer(ITIMER_REAL, &itv, NULL) == -1) err(EX_OSERR, "setitimer"); } while (nleft > 0) { n = kevent(kq, NULL, 0, e, nleft + tflag, NULL); if (n == -1) err(EX_OSERR, "kevent"); for (i = 0; i < n; i++) { if (e[i].filter == EVFILT_SIGNAL) { if (verbose) printf("timeout\n"); exit(124); } if (verbose) { status = e[i].data; if (WIFEXITED(status)) printf("%ld: exited with status %d.\n", (long)e[i].ident, WEXITSTATUS(status)); else if (WIFSIGNALED(status)) printf("%ld: killed by signal %d.\n", (long)e[i].ident, WTERMSIG(status)); else printf("%ld: terminated.\n", (long)e[i].ident); } --nleft; } } exit(EX_OK); }