From nobody Tue Nov 25 03:19:30 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 4dFnwz2grDz6HMnQ for ; Tue, 25 Nov 2025 03:19:31 +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 4dFnwy5dxHz3Tsl for ; Tue, 25 Nov 2025 03:19:30 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1764040770; 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=YVk/QmlSmymK88ji+syBQEKlLiLKuqcK4m208Ezcryk=; b=XlFUT5dA47mNrqzX6WBCRayUmUwnhXcUBWJiaVRH9q/ziDa+N3lk8c0Dod5MOVGECG2hcX p1WHpYxrByTMAUGwD6/0o4SAajTmYZB6yPP67hGT7syqMFlVuwBbNwXJAk5WnzzjyXgwXS Bxo8FOc2CSyAMKhSF/XNTnjaqYNNZb9O/g22BiHjFmpaqmaO1Af1N57o6AdI8ye3tycJUU e3uVBw+l9awo6/TogBjQkcNkvW59rJH+bSf5tDmyf77sBZakewiKUUWrKGEVKC6Th6Xyn/ jmg2I0pjEM6AcJUvsMSIfEEtbZn0R5mqStPG6Mz3LI+4S9YQ6R3uCebIQ+luWw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1764040770; 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=YVk/QmlSmymK88ji+syBQEKlLiLKuqcK4m208Ezcryk=; b=Gd9ixAbEZ5wOILMnMrVlkx1fGDUatk/3SSsRYvINb+/PwaSj3o5EAmi0qXRJs7TuJeRWOa vIDFlOTtahrM9EfBztTG3BX0AK1zKoZF1Q7fyHUtFHDZ5GOfHcLYetWNQmTQjGz3xK+lRS fKQhEwetmI5G6abY83l6jBG2WNSolx5LPlesCs165J6cfWkDcZHR5ywg49HnZjAJsH20aA EmhLElVeJEFk1iePsJiapZ2U/SSxILLsdbrf7GsRZua3BBe9O0EzPcxQHw59I0t+Q2vKwL NOw4tua5nFMDTt3+JJK2mutRA2sz5ZBjbIjpVhLH2Ht7D5LyeMRqHJBzW1F2ig== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1764040770; a=rsa-sha256; cv=none; b=ZHmibW/dvnYBkTD048DZcQ9Gcd7GRoBMsqbTMB2+g93CiCT3b/kLdxpVXE2bwo6TFuwhRp uwkWVm6h0G36jmsNSzdzX3LpR/9soFTQVzPewmbCeMAvxgA93c0WhRiZaqJZwsy+mX6cbQ XmzzBESdMUE3imfDN4JX54OBhEy2PDFaoMiZ3UEBAQBl6MS7FDHB8rwKOFkywgQW/MDjFT 9hjAHPfR31qmDh8KweDuzetV0UuEZdp5S5z9zj1Yfd4svqfndFr5OlhXGgLjjQwgLJduaM 8KfVCSpzqgAa//j5Hm+RNW+aDE8Ha75FDjXx/MgGXc+/WSmDvGPT9hrRPBOkPQ== 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 4dFnwy53swzk9Q for ; Tue, 25 Nov 2025 03:19:30 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 33b44 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 25 Nov 2025 03:19:30 +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: 7f691e07efe6 - stable/14 - sh: Don't assume EINTR means SIGALRM 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: des X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 7f691e07efe63ea01273833e44fd03ee00106b2b Auto-Submitted: auto-generated Date: Tue, 25 Nov 2025 03:19:30 +0000 Message-Id: <69252042.33b44.5f3748f@gitrepo.freebsd.org> The branch stable/14 has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=7f691e07efe63ea01273833e44fd03ee00106b2b commit 7f691e07efe63ea01273833e44fd03ee00106b2b Author: Dag-Erling Smørgrav AuthorDate: 2025-11-19 10:43:13 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2025-11-25 03:19:16 +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 39b3effb99df..70b2aac58e93 100644 --- a/bin/sh/miscbltin.c +++ b/bin/sh/miscbltin.c @@ -46,11 +46,14 @@ static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95"; #include #include #include -#include + #include +#include +#include #include #include #include +#include #include "shell.h" #include "options.h" @@ -168,17 +171,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': @@ -190,22 +194,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; } } @@ -218,13 +229,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 c11920e2f2a7..eb517b6938ee 100644 --- a/bin/sh/sh.1 +++ b/bin/sh/sh.1 @@ -33,7 +33,7 @@ .\" .\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95 .\" -.Dd March 8, 2025 +.Dd November 17, 2025 .Dt SH 1 .Os .Sh NAME @@ -2504,6 +2504,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 c3ed122791b5..56de5e57732b 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