From nobody Wed Nov 19 10:49:54 2025 X-Original-To: dev-commits-src-main@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 4dBJCQ492Kz6HVv9 for ; Wed, 19 Nov 2025 10:49:54 +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 4dBJCQ1k8qz3MZt for ; Wed, 19 Nov 2025 10:49:54 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1763549394; 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=jVWZZDuN1iemkXckkjIgkQ3+YMuAgmNyPRVB2ZMFQqY=; b=HODy729NJcJeGdecv5+d8drtduKH0xu5R9mS+DsxGMJ4hjRFhmd9OdMYDm+NUH2Fiq3TL1 tMvwxFIEZujPaCAmXSzD6brr9q0zemeL3HfOCRbtd0Heri0ekhEU4km2+dKw5NruNa5f30 nHN9YWegDbkdck5kDdoyiDcniEei9MuajQrzN2Mc4Xpqa742DZkJSVAiCMw10vqG7s3+XN i8zZzCFFrXJwy1ndI+sXSVXMuNB7HJnqRP+H9PBJ4dswg6K2qKbvPQ+rRqrBrwl6yq5U6R QN1pAiZx8vVBeUgbLDJrSH1vdl8PvR5BOtCwi4df6ZZGKwmDeKoEJSZMSKdJ2A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1763549394; 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=jVWZZDuN1iemkXckkjIgkQ3+YMuAgmNyPRVB2ZMFQqY=; b=DDGLOq/yIl8ew9Wx7OXNYzYJNp++dtGusUdtiqsn6l0ptFdePecGLSJ4MpVcZQ5huXErZu drWvXTce7lKVkdzIBbVBmotlwq5OHA+2NN9WVmlB121epO25BsK4yKstpcjgJMp+s6OCLM 1SIGfyo0JscyOK6KmWFxuYWtgDFNDnc6Z7gXLpcvVX+hjEs0DBLILoO59KZhhTZ4Lp0GYg uUiMgRKq/4vl5C/KHRu4YtLZuzC/J7cga4Q1XLkxchpvJuyMaoTgibXYWukYi7k5xSLKaL CWruZ7hZSjnlvuKe2ZdpznwEaEKHWOoALTz29h52hUP40KwWx0oggen6tD/nJw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1763549394; a=rsa-sha256; cv=none; b=Og1M75GsNEC7t+tPdqfqOiThHgVelOOiPif0fXoM8VLabQVmmOYSoP8J/uOMz8X5TMSOzN KC5Dj32XtPa/9wRONY7LXErQmMIB+Rr4UgPgLtd/LTr72lWmnJZJR3CIsPJhB2P8ytnIyE 1EgGEtgAmQLX0Yy492jtd9KzM7p939kJvbBl0xEloCdTiqdtLEfcaIbERqCtac6QRngwuS OJ9NeaI3M4oc9FRS4+Li0cMx460CfOeFgOy5KOWncyJAOtw38cYk2VS8hfIFnQ6UafHQOu 0GRnlErD4o9D12oqKpMKGZWOgpYt/ssItDIwvJ6CAlLL8KgitDzRGpl387Jwtg== 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 4dBJCQ113czdFw for ; Wed, 19 Nov 2025 10:49:54 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3f47e by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Wed, 19 Nov 2025 10:49:54 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Dag-Erling=?utf-8?Q? Sm=C3=B8rg?=rav Subject: git: 3c2643a7dbac - main - sh: Don't assume EINTR means SIGALRM List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@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/main X-Git-Reftype: branch X-Git-Commit: 3c2643a7dbac370b7232f4e5ac15fd77b9ff396d Auto-Submitted: auto-generated Date: Wed, 19 Nov 2025 10:49:54 +0000 Message-Id: <691da0d2.3f47e.332ff678@gitrepo.freebsd.org> The branch main has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=3c2643a7dbac370b7232f4e5ac15fd77b9ff396d commit 3c2643a7dbac370b7232f4e5ac15fd77b9ff396d Author: Dag-Erling Smørgrav AuthorDate: 2025-11-19 10:43:13 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2025-11-19 10:43:59 +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 --- 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 407d2aeaa061..0246009cce81 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