From nobody Tue Nov 25 03:19:26 2025 X-Original-To: dev-commits-src-all@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 4dFnwv23KPz6HM9c for ; Tue, 25 Nov 2025 03:19:27 +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 4dFnwt6g3Nz3Tnd for ; Tue, 25 Nov 2025 03:19:26 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1764040767; 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=5eraX2N5PUNj928e/TZ3C+PRP6R0ogc3ee7ECi9RVvA=; b=OO3MZjxTiFtoX2O5+cToSE6/Q0fz8Ms4MICHnZqNiINm/CxXvWbJFWE9ZgUdqVkJozsWIe m0YjVbG+oeLwxjWiCNPPihmNfvoaisXTIGjWCSXby4TqgGkjwCHj37NnLG5Elz2GFFbvqq /yUcV5Vv0giO4hmDXSG9lyLt1TD6XPudYfrxFSjS4+HZHTlzA9HRiMfH7+sQsVnqgejvYq 9RVZKsHDURr0weDmZdMk8FBae4aFmR3bqCWIyaKuQBo3svvhrAnUkg7vq8mBQT+b5kdwbt eNJ9Gz9VV3aB+6q+zMLwJr3IoYJEm3BS1xTHnGwIxG/52webve1ZL8JOZAHfkA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1764040767; 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=5eraX2N5PUNj928e/TZ3C+PRP6R0ogc3ee7ECi9RVvA=; b=w1Mmg9PghbweoQi19CzabyG7nAuxsHYTTW/fDJC1CMkDt0odjTGNE3NSL1GkTjzB6Ie4l4 F7vxwZmz848vDR4hmiF4jjRsLDknQWUgqaPcaH96HD79OrW2kFqpLH6jTi1IH7lazl9som DfvFXV2IBlCoVGXoifuJ6TdZV74PGtNusD/Sf9EJbpxFtITnflMh7mWzJkbIG6+LdYchV6 T0p0gl8bEVvBWCsje3UEzmzWmr+ZNyTShkKmzoxVxNUSKl/a9sxs1Y37AJf+TSJ9P7uimz l/MgDvAJh9h7IF59pRDXd2HaVgNaBZ6yns+I8/4/EZMFwDLY+fZVMmEtfOKT6Q== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1764040767; a=rsa-sha256; cv=none; b=QefNf25xkkjTesxdf3rvDR+y1e05eTjtaL8AsVSJgiQ06mpgfBdWu5ccX1kMiQo0/mdSe/ g+OALzMOzvygeWNEAHqgCu1z93mkG0Vki2ovwIBsLNq9tgTVLUyow/zngfQaS4UTAK2AWU ZKMSOE+IJRjVe+j6IpM098vw481eF42gVEYHldxq4ZrHd/eVlR8hf9h4Qs4/BjXh1bqtEJ 6RkkdzQPeMjfwyV2pgxC5oTSW9nIbiM+x2cmYd1+C8DjnCxaKgaLS0H0QSPnZMHhBo5Zkk SbY9i5lfxIcLb/Vqt6GxTzPvAiwXbq0ALhaSVkuaXGeOztUUrbxCtX8oEvBE5A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4dFnwt5vwhzkQR for ; Tue, 25 Nov 2025 03:19:26 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 33dbe by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 25 Nov 2025 03:19:26 +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: fb57eac42c15 - stable/15 - sh: Don't assume EINTR means SIGALRM List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org 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: fb57eac42c1598119aa8614f3886dca0379ae816 Auto-Submitted: auto-generated Date: Tue, 25 Nov 2025 03:19:26 +0000 Message-Id: <6925203e.33dbe.3a581c57@gitrepo.freebsd.org> The branch stable/15 has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=fb57eac42c1598119aa8614f3886dca0379ae816 commit fb57eac42c1598119aa8614f3886dca0379ae816 Author: Dag-Erling Smørgrav AuthorDate: 2025-11-19 10:43:13 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2025-11-25 03:18:24 +0000 sh: Don't assume EINTR means SIGALRM While waiting for input in the read builtin, if select() is interrupted but there is no pending signal, we act like we timed out, and return the same status as if we had been interrupted by SIGALRM, instead of looping until we actually do time out. * Replace the single select() call with a ppoll() loop. * Improve validation of the timeout value. We now accept things like "1h30m15s", which we used to silently truncate to "1h". The flip side is that we no longer accept things like "1hour" or "5sec". * Modify the existing `read -t 0` test case to verify that read returns immediately when there is input and fails immediately when there isn't. * Add a second test case which performs the same tests with a non-zero timeout value. PR: 290844 MFC after: 1 week Fixes: c4539460e3a4 ("sh: Improve error handling in read builtin:") Reviewed by: jilles, bdrewery Differential Revision: https://reviews.freebsd.org/D53761 (cherry picked from commit 3c2643a7dbac370b7232f4e5ac15fd77b9ff396d) --- bin/sh/miscbltin.c | 83 +++++++++++++++++++++++++++++------------- bin/sh/sh.1 | 6 ++- bin/sh/tests/builtins/Makefile | 1 + bin/sh/tests/builtins/read11.0 | 19 +++++++++- bin/sh/tests/builtins/read12.0 | 32 ++++++++++++++++ 5 files changed, 112 insertions(+), 29 deletions(-) diff --git a/bin/sh/miscbltin.c b/bin/sh/miscbltin.c index 9d0280bb548a..bbf0aa5b8bde 100644 --- a/bin/sh/miscbltin.c +++ b/bin/sh/miscbltin.c @@ -40,11 +40,14 @@ #include #include #include -#include + #include +#include +#include #include #include #include +#include #include "shell.h" #include "options.h" @@ -162,17 +165,18 @@ readcmd(int argc __unused, char **argv __unused) int is_ifs; int saveall = 0; ptrdiff_t lastnonifs, lastnonifsws; - struct timeval tv; - char *tvptr; - fd_set ifds; + sigset_t set, oset; + intmax_t number, timeout; + struct timespec tnow, tend, tresid; + struct pollfd pfd; + char *endptr; ssize_t nread; int sig; struct fdctx fdctx; rflag = 0; prompt = NULL; - tv.tv_sec = -1; - tv.tv_usec = 0; + timeout = -1; while ((i = nextopt("erp:t:")) != '\0') { switch(i) { case 'p': @@ -184,22 +188,29 @@ readcmd(int argc __unused, char **argv __unused) rflag = 1; break; case 't': - tv.tv_sec = strtol(shoptarg, &tvptr, 0); - if (tvptr == shoptarg) - error("timeout value"); - switch(*tvptr) { - case 0: - case 's': - break; - case 'h': - tv.tv_sec *= 60; - /* FALLTHROUGH */ - case 'm': - tv.tv_sec *= 60; - break; - default: - error("timeout unit"); - } + timeout = 0; + do { + number = strtol(shoptarg, &endptr, 0); + if (number < 0 || endptr == shoptarg) + error("timeout value"); + switch (*endptr) { + case 's': + endptr++; + break; + case 'h': + number *= 60; + /* FALLTHROUGH */ + case 'm': + number *= 60; + endptr++; + break; + } + if (*endptr != '\0' && + !(*endptr >= '0' && *endptr <= '9')) + error("timeout unit"); + timeout += number; + shoptarg = endptr; + } while (*shoptarg != '\0'); break; } } @@ -212,13 +223,33 @@ readcmd(int argc __unused, char **argv __unused) if ((ifs = bltinlookup("IFS", 1)) == NULL) ifs = " \t\n"; - if (tv.tv_sec >= 0) { + if (timeout >= 0) { /* * Wait for something to become available. */ - FD_ZERO(&ifds); - FD_SET(0, &ifds); - status = select(1, &ifds, NULL, NULL, &tv); + pfd.fd = STDIN_FILENO; + pfd.events = POLLIN; + status = sig = 0; + sigfillset(&set); + sigprocmask(SIG_SETMASK, &set, &oset); + if (pendingsig) { + /* caught a signal already */ + status = -1; + } else if (timeout == 0) { + status = poll(&pfd, 1, 0); + } else { + clock_gettime(CLOCK_UPTIME, &tnow); + tend = tnow; + tend.tv_sec += timeout; + do { + timespecsub(&tend, &tnow, &tresid); + status = ppoll(&pfd, 1, &tresid, &oset); + if (status >= 0 || pendingsig != 0) + break; + clock_gettime(CLOCK_UPTIME, &tnow); + } while (timespeccmp(&tnow, &tend, <)); + } + sigprocmask(SIG_SETMASK, &oset, NULL); /* * If there's nothing ready, return an error. */ diff --git a/bin/sh/sh.1 b/bin/sh/sh.1 index 7ef22fa352bb..affb653cd3ae 100644 --- a/bin/sh/sh.1 +++ b/bin/sh/sh.1 @@ -31,7 +31,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 1, 2025 +.Dd November 17, 2025 .Dt SH 1 .Os .Sh NAME @@ -2544,6 +2544,10 @@ to explicitly specify seconds, minutes or hours. If none is supplied, .Ql s is assumed. +Multiple value-unit groups may be stringed together, in which case +they are added up, e.g.\& +.Ql 1h30m15s +which adds up to 5,415 seconds. .Pp The .Fl e diff --git a/bin/sh/tests/builtins/Makefile b/bin/sh/tests/builtins/Makefile index 7fdecb23c817..b3e353024969 100644 --- a/bin/sh/tests/builtins/Makefile +++ b/bin/sh/tests/builtins/Makefile @@ -143,6 +143,7 @@ ${PACKAGE}FILES+= read8.0 ${PACKAGE}FILES+= read9.0 ${PACKAGE}FILES+= read10.0 ${PACKAGE}FILES+= read11.0 +${PACKAGE}FILES+= read12.0 ${PACKAGE}FILES+= return1.0 ${PACKAGE}FILES+= return2.1 ${PACKAGE}FILES+= return3.1 diff --git a/bin/sh/tests/builtins/read11.0 b/bin/sh/tests/builtins/read11.0 index 5bae80318b15..07bd3e70644c 100644 --- a/bin/sh/tests/builtins/read11.0 +++ b/bin/sh/tests/builtins/read11.0 @@ -1,3 +1,5 @@ +# Verify that `read -t 0 v` succeeds immediately if input is available +# and fails immediately if not set -e @@ -6,12 +8,25 @@ trap 'rm -rf "$T"' 0 cd $T mkfifo fifo1 # Open fifo1 for writing -{ sleep 10; } >fifo1 & +{ echo new_value; sleep 10; } >fifo1 & # Wait for the child to open fifo1 for writing exec 3fifo1 & +# Wait for the child to open fifo1 for writing +exec 3