From nobody Thu Oct 30 23:52:28 2025 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4cyLWc6YnDz6FnKw; Thu, 30 Oct 2025 23:52:28 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4cyLWc3TvRz3cdg; Thu, 30 Oct 2025 23:52:28 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1761868348; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=TdCR8LMJG+3nVGoVd/ll13H3hfTzfuC2P/Hy5D/gQjA=; b=rK56YdQi81TF0Ih07yydk/XrnSPy0vrtSN+tNE+TTfxG+wDWMa8RUcGN9T4N04W26zA46O e0DjCzLNOiNwG7/IxtFMvANZCFW7mpIp4bHsqbEA4gT2mSDlgb5RWNaCEufOnF/Sz4YlQK vbNKIzXCkimpR/Jh265vesi+xyIIw354fUSwxN8kj3GK94MkAQCzawxDn/rdUNBCDhqGqv sQXpV7PmLn7lPRLeWsAUmxbmwSlotoKR19MKRwYtBK2sZOFwptUVHAIjY1skAAr+f5JG/l 3ylT2frKIPaQUKbt2ATBqS7I8MaBmt0GFj0TlyEEf7mB8HpGB8yZCS/4NAw+dQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1761868348; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=TdCR8LMJG+3nVGoVd/ll13H3hfTzfuC2P/Hy5D/gQjA=; b=Wb8zDHM3/ZbQrLiVsxM75cY1EeuNGlBgu4ZzG//zZo+ntGbYzNr8Gs6eQEBIC2WSSbi5SB AMDVa3zx41hwH8qlRGIQEma8hKA/0RdT7+5iRuslGdN5gyBP9kIAL6dqH5xFf/gPSB08mB hiD5WwnPcEjAFBoWpOBjPLfG0VOxyzq9nCKPcimzycp9T6EgZjM40ExK/aZjcfaw0v+grW J+GnRenS7wTmdFH2evabY+xi4B01vEx1MGZwa/hXV1/FR20yIfgfEFKblEOkHIUHCeOUcc D/5pOCvCZUbIwPMh8NzsVQ91aQNAFBShayj2fcdG1AmycExAZJgKLsGKgov55Q== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1761868348; a=rsa-sha256; cv=none; b=gK9keSKUIsNCUj7ePaZT+fWOADzuzbWhrT4vdyOh/mddFOGGFcvj4FzsA+WkAv/LMXnr6c FLdywqikMJyUefLm6YvWpbdJ/HAMJuRjzS0ZYPUGMpIUSOVcOnXxD/cbEskRM9jsFklkCv krrOUifSfO2NB5g8MtIH0Dh01mzmEuRTgMUgm93zlsB8fIZoxIuV7mVHmJNYbEav22mi75 SXjVeiYBzF1V8lxRWprqJ5/H70uupxOUmLfuCXXetU6uiUplnq8Gm/iLcT0KMjWjU7PB6r 1hJdoRHuiAdHrcgD9pXNFR6gHaPJhg8Cu9eKZenjyux1P643UPiLbCpi4vydDA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4cyLWc34pzzlXs; Thu, 30 Oct 2025 23:52:28 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 59UNqSRQ087572; Thu, 30 Oct 2025 23:52:28 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 59UNqSaN087557; Thu, 30 Oct 2025 23:52:28 GMT (envelope-from git) Date: Thu, 30 Oct 2025 23:52:28 GMT Message-Id: <202510302352.59UNqSaN087557@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Colin Percival Subject: git: b763c111ad2e - releng/15.0 - pwait: Add an option to print remaining processes List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: cperciva X-Git-Repository: src X-Git-Refname: refs/heads/releng/15.0 X-Git-Reftype: branch X-Git-Commit: b763c111ad2ecc22387b07f71842b1b1ab317835 Auto-Submitted: auto-generated The branch releng/15.0 has been updated by cperciva: URL: https://cgit.FreeBSD.org/src/commit/?id=b763c111ad2ecc22387b07f71842b1b1ab317835 commit b763c111ad2ecc22387b07f71842b1b1ab317835 Author: Dag-Erling Smørgrav AuthorDate: 2025-10-28 11:56:36 +0000 Commit: Colin Percival CommitDate: 2025-10-30 23:48:25 +0000 pwait: Add an option to print remaining processes * On startup, insert all valid PIDs into a tree. * In our main loop, whenever a process terminates, remove its PID from the tree. * On exit, if the -p flag was specified, print the remaining PIDs. Approved by: re (cperciva) MFC after: 3 days Reviewed by: bcr, markj Differential Revision: https://reviews.freebsd.org/D53293 (cherry picked from commit 3d73146baeb933fe955c7496572b483a9f92914c) (cherry picked from commit 955650f1814257070f8414b6b6e8f42496f26409) --- bin/pwait/pwait.1 | 6 ++- bin/pwait/pwait.c | 98 ++++++++++++++++++++++++++++--------------- bin/pwait/tests/pwait_test.sh | 38 +++++++++++++++++ 3 files changed, 107 insertions(+), 35 deletions(-) diff --git a/bin/pwait/pwait.1 b/bin/pwait/pwait.1 index 83ac8bcef317..d92b829b1d6a 100644 --- 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 @@ The following option is available: .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 index 27f4c8e9858d..59bf0eb93ced 100644 --- a/bin/pwait/pwait.c +++ b/bin/pwait/pwait.c @@ -33,7 +33,9 @@ #include #include +#include #include +#include #include #include @@ -46,10 +48,25 @@ #include #include +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,22 +78,28 @@ main(int argc, char *argv[]) { struct itimerval itv; struct kevent *e; + struct pid k, *p; char *end, *s; double timeout; + size_t sz; long pid; pid_t mypid; - 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; @@ -128,16 +151,17 @@ main(int argc, char *argv[]) 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; mypid = getpid(); for (n = 0; n < argc; n++) { s = argv[n]; @@ -147,7 +171,7 @@ main(int argc, char *argv[]) } 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; } @@ -155,27 +179,29 @@ main(int argc, char *argv[]) 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. @@ -190,7 +216,8 @@ main(int argc, char *argv[]) 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"); @@ -200,29 +227,34 @@ main(int argc, char *argv[]) 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 index 66bdd6981704..d31ca21cff93 100644 --- a/bin/pwait/tests/pwait_test.sh +++ b/bin/pwait/tests/pwait_test.sh @@ -310,6 +310,43 @@ or_flag_cleanup() 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:"$p5\n$p10\n" \ + -s exit:124 \ + pwait -t 2 -p $p10 $p5 $p1 $p5 $p10 + + atf_check \ + -e inline:"kill: $p1: No such process\n" \ + -s exit:1 \ + kill -0 $p1 + + atf_check 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 +355,5 @@ atf_init_test_cases() atf_add_test_case timeout_no_timeout atf_add_test_case timeout_many atf_add_test_case or_flag + atf_add_test_case print }