Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F151178614
D53293.id164866.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D53293.id164866.diff
View Options
diff --git a/bin/pwait/pwait.1 b/bin/pwait/pwait.1
--- a/bin/pwait/pwait.1
+++ b/bin/pwait/pwait.1
@@ -30,7 +30,7 @@
.\" USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
.\" OF SUCH DAMAGE.
.\"
-.Dd January 21, 2021
+.Dd October 22, 2025
.Dt PWAIT 1
.Os
.Sh NAME
@@ -39,7 +39,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl t Ar duration
-.Op Fl ov
+.Op Fl opv
.Ar pid
\&...
.Sh DESCRIPTION
@@ -51,6 +51,8 @@
.Bl -tag -width indent
.It Fl o
Exit when any of the given processes has terminated.
+.It Fl p
+On exit, print a list of processes that have not terminated.
.It Fl t Ar duration
If any process is still running after
.Ar duration ,
diff --git a/bin/pwait/pwait.c b/bin/pwait/pwait.c
--- a/bin/pwait/pwait.c
+++ b/bin/pwait/pwait.c
@@ -33,7 +33,9 @@
#include <sys/types.h>
#include <sys/event.h>
+#include <sys/sysctl.h>
#include <sys/time.h>
+#include <sys/tree.h>
#include <sys/wait.h>
#include <err.h>
@@ -46,10 +48,25 @@
#include <sysexits.h>
#include <unistd.h>
+struct pid {
+ RB_ENTRY(pid) entry;
+ pid_t pid;
+};
+
+static int
+pidcmp(const struct pid *a, const struct pid *b)
+{
+ return (a->pid > b->pid ? 1 : a->pid < b->pid ? -1 : 0);
+}
+
+RB_HEAD(pidtree, pid);
+static struct pidtree pids = RB_INITIALIZER(&pids);
+RB_GENERATE_STATIC(pidtree, pid, entry, pidcmp);
+
static void
usage(void)
{
- fprintf(stderr, "usage: pwait [-t timeout] [-ov] pid ...\n");
+ fprintf(stderr, "usage: pwait [-t timeout] [-opv] pid ...\n");
exit(EX_USAGE);
}
@@ -61,21 +78,27 @@
{
struct itimerval itv;
struct kevent *e;
+ struct pid k, *p;
char *end, *s;
double timeout;
+ size_t sz;
long pid;
- int i, kq, n, nleft, opt, status;
- bool oflag, tflag, verbose;
+ int i, kq, n, ndone, nleft, opt, pid_max, ret, status;
+ bool oflag, pflag, tflag, verbose;
oflag = false;
+ pflag = false;
tflag = false;
verbose = false;
memset(&itv, 0, sizeof(itv));
- while ((opt = getopt(argc, argv, "ot:v")) != -1) {
+ while ((opt = getopt(argc, argv, "opt:v")) != -1) {
switch (opt) {
case 'o':
- oflag = 1;
+ oflag = true;
+ break;
+ case 'p':
+ pflag = true;
break;
case 't':
tflag = true;
@@ -127,16 +150,17 @@
usage();
}
- kq = kqueue();
- if (kq == -1) {
+ if ((kq = kqueue()) < 0)
err(EX_OSERR, "kqueue");
- }
- e = malloc((argc + tflag) * sizeof(struct kevent));
- if (e == NULL) {
+ sz = sizeof(pid_max);
+ if (sysctlbyname("kern.pid_max", &pid_max, &sz, NULL, 0) != 0) {
+ pid_max = 99999;
+ }
+ if ((e = malloc((argc + tflag) * sizeof(*e))) == NULL) {
err(EX_OSERR, "malloc");
}
- nleft = 0;
+ ndone = nleft = 0;
for (n = 0; n < argc; n++) {
s = argv[n];
/* Undocumented Solaris compat */
@@ -145,7 +169,7 @@
}
errno = 0;
pid = strtol(s, &end, 10);
- if (pid < 0 || *end != '\0' || errno != 0) {
+ if (pid < 0 || pid > pid_max || *end != '\0' || errno != 0) {
warnx("%s: bad process id", s);
continue;
}
@@ -153,27 +177,29 @@
warnx("%s: skipping my own pid", s);
continue;
}
- for (i = 0; i < nleft; i++) {
- if (e[i].ident == (uintptr_t)pid) {
- break;
- }
+ if ((p = malloc(sizeof(*p))) == NULL) {
+ err(EX_OSERR, NULL);
}
- if (i < nleft) {
+ p->pid = pid;
+ if (RB_INSERT(pidtree, &pids, p) != NULL) {
/* Duplicate. */
+ free(p);
continue;
}
EV_SET(e + nleft, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1) {
+ if (errno != ESRCH)
+ err(EX_OSERR, "kevent()");
warn("%ld", pid);
- if (oflag) {
- exit(EX_OK);
- }
+ RB_REMOVE(pidtree, &pids, p);
+ free(p);
+ ndone++;
} else {
nleft++;
}
}
- if (nleft > 0 && tflag) {
+ if ((ndone == 0 || !oflag) && nleft > 0 && tflag) {
/*
* Explicitly detect SIGALRM so that an exit status of 124
* can be returned rather than 142.
@@ -188,7 +214,8 @@
err(EX_OSERR, "setitimer");
}
}
- while (nleft > 0) {
+ ret = EX_OK;
+ while ((ndone == 0 || !oflag) && ret == EX_OK && nleft > 0) {
n = kevent(kq, NULL, 0, e, nleft + tflag, NULL);
if (n == -1) {
err(EX_OSERR, "kevent");
@@ -198,29 +225,34 @@
if (verbose) {
printf("timeout\n");
}
- exit(124);
+ ret = 124;
}
+ pid = e[i].ident;
if (verbose) {
status = e[i].data;
if (WIFEXITED(status)) {
printf("%ld: exited with status %d.\n",
- (long)e[i].ident,
- WEXITSTATUS(status));
+ pid, WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("%ld: killed by signal %d.\n",
- (long)e[i].ident,
- WTERMSIG(status));
+ pid, WTERMSIG(status));
} else {
- printf("%ld: terminated.\n",
- (long)e[i].ident);
+ printf("%ld: terminated.\n", pid);
}
}
- if (oflag) {
- exit(EX_OK);
+ k.pid = pid;
+ if ((p = RB_FIND(pidtree, &pids, &k)) != NULL) {
+ RB_REMOVE(pidtree, &pids, p);
+ free(p);
+ ndone++;
}
--nleft;
}
}
-
- exit(EX_OK);
+ if (pflag) {
+ RB_FOREACH(p, pidtree, &pids) {
+ printf("%d\n", p->pid);
+ }
+ }
+ exit(ret);
}
diff --git a/bin/pwait/tests/pwait_test.sh b/bin/pwait/tests/pwait_test.sh
--- a/bin/pwait/tests/pwait_test.sh
+++ b/bin/pwait/tests/pwait_test.sh
@@ -310,6 +310,47 @@
wait $p2 $p4 $p6 >/dev/null 2>&1
}
+atf_test_case print
+print_head()
+{
+ atf_set "descr" "Test the -p flag"
+}
+
+print_body()
+{
+ sleep 1 &
+ p1=$!
+
+ sleep 5 &
+ p5=$!
+
+ sleep 10 &
+ p10=$!
+
+ atf_check \
+ -o inline:"$p10\n" \
+ -s exit:124 \
+ pwait -t 6 -p $p1 $p5 $p10
+
+ atf_check \
+ -e inline:"kill: $p1: No such process\n" \
+ -s exit:1 \
+ kill -0 $p1
+
+ atf_check \
+ -e inline:"kill: $p5: No such process\n" \
+ -s exit:1 \
+ kill -0 $p5
+
+ atf_check kill -0 $p10
+}
+
+print_cleanup()
+{
+ kill $p1 $p5 $p10 >/dev/null 2>&1
+ wait $p1 $p5 $p10 >/dev/null 2>&1
+}
+
atf_init_test_cases()
{
atf_add_test_case basic
@@ -318,4 +359,5 @@
atf_add_test_case timeout_no_timeout
atf_add_test_case timeout_many
atf_add_test_case or_flag
+ atf_add_test_case print
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Apr 7, 3:18 PM (18 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31039174
Default Alt Text
D53293.id164866.diff (5 KB)
Attached To
Mode
D53293: pwait: Add an option to print remaining processes
Attached
Detach File
Event Timeline
Log In to Comment