From nobody Mon Aug 3 11:38:42 2026 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 4hDF772yrCz6nCHL for ; Mon, 03 Aug 2026 11:38:43 +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 "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hDF765FYfz3Rw4 for ; Mon, 03 Aug 2026 11:38:42 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1785757122; 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=WP2hfWok+K4Opl5Z7nWEWc1LEO/6rby3obyMAUAaKoo=; b=rfB/2vyhWnDM2zxtLbZHicjnQmank2v8d0WBf50WaP5Yl+XnM3bJVKIzytVOvNf+T4NH7S TVIDQ/Q/94S5XJLu3x/wYK7pEVNJbyVXJ8QGCMTXh1fgiSA1F5tdYbpMNFvLYFlCGkre9+ rM6b3+bEH6mcktmnFNyH4n3HKHUF9+iX5Grw5y5SnX2LRX61t7EnDBzoPaH++ZT5JHw10M gqU858qIELY6mwoDWNc5FfnKIAw1UCNRkAQLp/F57b5NjP1DeL0Rl/XViqVuLaVHVJB2xp ZKFjWT6LUyfnH0u0lOW/OsPAmrOCuIsw/eQDAuiwVxBasZe2ixDG71pteyg8xg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1785757122; a=rsa-sha256; cv=none; b=wA/eFYsRzLfmWDPXBjp1IMZVoc3oHgMiT4TaYmQor1ZPSS+C+vi806hzXmSdBwtjdI3Kkn 0Aexu4H9bJpykgEPByi89kdy8jZfDv5o0JtzMQXVwYqpuRHjKsHlqmZZbJlOJw1XYWrapk RmE/AvpgWjQvGiGZJlEicrzSYcuTg6GA61B6u8ZL4TVJEV8Sf2hV03PnBVa1VQgTsMGsn0 0O3LtRlBt+vqsVTsvJ7llIX1/tBybZx7Sfudqpfr1ZcUmMKJHWoKtd2AU/gzwGafAznFJh 01zWrdvmj6JcJwGyZRngC2dACILHiX/Hkf6v1pU+eG7ujkb8wwX2D2nRsMbB3w== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1785757122; 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=WP2hfWok+K4Opl5Z7nWEWc1LEO/6rby3obyMAUAaKoo=; b=WNMT3EcEgJVoGliyktr+jmIkWUl7labl+ywanIwfn8iHW0PSQyBBui8NIwW7yyryyaYq3q 2VOBi1HXA3eiqkl5R2Ny2sScQfF51qTSQ/uGpcnYDYm/DsDozGDzUmRmecNkW4FkpnCUqJ I7ambDipQOlgeuwa8aiRsj/EdJwSmZjOmTkGJVhrEWEck0oFcZQyNoUSAUnnGgmezLYTJs g8CjQJYsIfVWXEyQo9KQeQ3STkOCg7TP8Mxp0itO76IQxyeKByQwsc8UEPkMITg2/RFor/ aUglNjHqyj8BRifIkGBEIPNPF/xdhon9cvjlbGp8LBfBEfUm3xM6cD1+YDKngg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hDF763xVkzyhQ for ; Mon, 03 Aug 2026 11:38:42 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1be8f by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 03 Aug 2026 11:38:42 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Dag-Erling=?utf-8?Q? Sm=C3=B8rg?=rav Subject: git: e87afada8e8a - stable/15 - pwait: Test the new -r option 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 List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: des X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: e87afada8e8ad34e9ddb91073ec112835f1ef57d Auto-Submitted: auto-generated Date: Mon, 03 Aug 2026 11:38:42 +0000 Message-Id: <6a707dc2.1be8f.40e7dc33@gitrepo.freebsd.org> The branch stable/15 has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=e87afada8e8ad34e9ddb91073ec112835f1ef57d commit e87afada8e8ad34e9ddb91073ec112835f1ef57d Author: Dag-Erling Smørgrav AuthorDate: 2026-07-27 10:15:41 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2026-08-03 11:32:12 +0000 pwait: Test the new -r option Test that pwait without -r reports a process as soon as it terminates, while pwait with -r does not report it until it has been reaped. MFC after: 1 week Sponsored by: Klara, Inc. Sponsored by: NetApp, Inc. Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D58385 (cherry picked from commit e115066370dcfec410d914362756d09c268a5b4e) --- bin/pwait/tests/Makefile | 1 + bin/pwait/tests/pwait_reap.c | 188 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+) diff --git a/bin/pwait/tests/Makefile b/bin/pwait/tests/Makefile index 4e355ccfe787..0f9359c92593 100644 --- a/bin/pwait/tests/Makefile +++ b/bin/pwait/tests/Makefile @@ -1,3 +1,4 @@ +ATF_TESTS_C= pwait_reap ATF_TESTS_SH= pwait_test .include diff --git a/bin/pwait/tests/pwait_reap.c b/bin/pwait/tests/pwait_reap.c new file mode 100644 index 000000000000..96c036ba2059 --- /dev/null +++ b/bin/pwait/tests/pwait_reap.c @@ -0,0 +1,188 @@ +/*- + * Copyright (c) 2026 Dag-Erling Smørgrav + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * Wait for a process to terminate, optionally reap it, and verify that it + * exited cleanly. + */ +static void +wait_zero(pid_t pid, bool reap) +{ + int wstatus; + pid_t ret; + + do { + ret = waitpid(pid, &wstatus, reap ? 0 : WNOWAIT); + ATF_REQUIRE(ret == pid || (ret < 0 && errno == EINTR)); + } while (ret != pid); + ATF_CHECK(WIFEXITED(wstatus)); + ATF_CHECK_EQ(WEXITSTATUS(wstatus), 0); +} + +/* + * Verify that pwait is still waiting for the target process. + */ +static void +pwait_is_waiting(pid_t pwpid, pid_t tpid, int pwout, int pwerr) +{ + struct pollfd pfds[2]; + char line[64] = "", *eol, *rest; + ssize_t ret; + + pfds[0].fd = pwout; + pfds[0].events = POLLIN; + pfds[1].fd = pwerr; + pfds[1].events = POLLIN; + + /* loop until we have some output */ + do { + /* send SIGINFO so pwait prints the target PID on stderr */ + ATF_REQUIRE(kill(pwpid, SIGINFO) == 0); + } while ((ret = poll(pfds, 2, 100)) == 0); + ATF_REQUIRE_EQ(ret, 1); + ATF_REQUIRE_EQ(pfds[1].revents, POLLIN); + + /* read line from stderr */ + ATF_REQUIRE((ret = read(pwerr, line, sizeof(line) - 1)) > 0); + + /* verify the line */ + ATF_REQUIRE((eol = strchr(line, '\n')) != NULL); + *eol = '\0'; + ATF_REQUIRE_EQ(strtol(line, &rest, 10), tpid); + ATF_REQUIRE_STREQ(rest, ""); +} + +/* + * Verify that pwait has reported that the target process has terminated, + * then reap it. + */ +static void +pwait_is_done(pid_t pwpid, pid_t tpid, int pwout, int pwerr) +{ + struct pollfd pfds[2]; + char line[64] = "", *eol, *rest; + ssize_t ret; + + pfds[0].fd = pwout; + pfds[0].events = POLLIN; + pfds[1].fd = pwerr; + pfds[1].events = POLLIN; + + /* loop until we have some output */ + do { + /* nothing */ + } while ((ret = poll(pfds, 2, 100)) == 0); + ATF_REQUIRE_EQ(ret, 1); + ATF_REQUIRE_EQ(pfds[0].revents, POLLIN); + + /* read line from stdout */ + ATF_REQUIRE((ret = read(pwout, line, sizeof(line) - 1)) > 0); + + /* verify the line */ + ATF_REQUIRE((eol = strchr(line, '\n')) != NULL); + *eol = '\0'; + ATF_REQUIRE_EQ(strtol(line, &rest, 10), tpid); + ATF_REQUIRE_STREQ(rest, ": exited with status 0."); + + /* reap pwait */ + wait_zero(pwpid, true); +} + +static void +pwait_reap_test(bool reap) +{ + char pidstr[16]; + pid_t tpid, pwpid; + int tpipe[2], pwout[2], pwerr[2]; + + /* fork target process */ + ATF_REQUIRE(pipe2(tpipe, O_CLOEXEC) == 0); + ATF_REQUIRE((tpid = fork()) >= 0); + if (tpid == 0) { + (void)close(tpipe[1]); + /* block until parent closes its end of the pipe */ + (void)read(tpipe[0], pidstr, 1); + _exit(0); + } + (void)close(tpipe[0]); + + /* fork pwait */ + snprintf(pidstr, sizeof(pidstr), "%ld", (long)tpid); + ATF_REQUIRE(pipe2(pwout, O_CLOEXEC) == 0); + ATF_REQUIRE(pipe2(pwerr, O_CLOEXEC) == 0); + ATF_REQUIRE((pwpid = fork()) >= 0); + if (pwpid == 0) { + (void)dup2(pwout[0], STDOUT_FILENO); + (void)dup2(pwerr[0], STDERR_FILENO); + execlp("pwait", "pwait", reap ? "-rv" : "-v", pidstr, NULL); + _exit(99); + } + + /* wait for pwait to become ready */ + pwait_is_waiting(pwpid, tpid, pwout[1], pwerr[1]); + + /* unblock the target and wait for it to terminate */ + (void)close(tpipe[1]); + wait_zero(tpid, false); + + if (reap) { + /* check that pwait is still waiting */ + pwait_is_waiting(pwpid, tpid, pwout[1], pwerr[1]); + } else { + /* check that pwait has reported completion */ + pwait_is_done(pwpid, tpid, pwout[1], pwerr[1]); + } + + /* reap the target */ + wait_zero(tpid, true); + + if (reap) { + /* check that pwait has reported completion */ + pwait_is_done(pwpid, tpid, pwout[1], pwerr[1]); + } +} + +ATF_TC(pwait_normal); +ATF_TC_HEAD(pwait_normal, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test that pwait returns before the " + "target process has been reaped"); +} +ATF_TC_BODY(pwait_normal, tc) +{ + pwait_reap_test(true); +} + +ATF_TC(pwait_reap); +ATF_TC_HEAD(pwait_reap, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test that pwait -r does not return " + "until the target process has been reaped"); +} +ATF_TC_BODY(pwait_reap, tc) +{ + pwait_reap_test(true); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, pwait_normal); + ATF_TP_ADD_TC(tp, pwait_reap); + return (atf_no_error()); +}