From nobody Wed Apr 16 19:46:38 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 4ZdBNt6XHgz5t8T1; Wed, 16 Apr 2025 19:46:38 +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 "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4ZdBNt3k34z3lRv; Wed, 16 Apr 2025 19:46:38 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1744832798; 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=7PlVAn8VdvBBO/Q3WAQqKCX/WpAaTMaBKhVYmd5a4dI=; b=R8CaA5lx0JOibFoU1Ol/d+WpMxImVd0A7k4/aMBPh1xtpDD2dMaiC7aN6XwLg633d+NO3W bVzi9xBWRVRPcPhXAviAAjx5LX5jcpbiCnrsLZ0jTj/5w6H5mpqtR7d9/d+iJ4WQeAq5wN c0AmvXjV7t2EhqhT2BsYtJaGgb49jJL66fFL19dwPSPgGSiG5ZP0fbyK1mLuypQIhc+7Ea 1c5gxiJfmXE5GZbWmVmHo5cwlxjEMrBMvqJ+2/zvayXKh2+xwmY9z19pbJQK/U4hHa/FOr Zaoid1j+7TdWT4cFUaQwauOowZUsdMd9tLyPw8AEWsaKPde9TGTAnzZq4gWVAQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1744832798; a=rsa-sha256; cv=none; b=Uy2vzmTmjCHaVBi9t96+tlKI7uIRfQPEwn3QYSyBzr9feE+oLq+Gh/kjBuB5icFsW1XJRf 20KMCO74dSfQtLxW34hGhk29rvqtDbjD2HJkJvncreIR3NwVEpjA+WzfulkzORDoY0m1Bt 4KWieKaAGJ+fwWu8+kduPpb/qU+y35LhJIlRD3BeWl2xzDsN3lhCsMMgzV8iXOcRbJ52Df 0xDR2yNRs6OR2LJzGqAyiaefTIGFVX9dd7Ckb6ZpW+RvWM1BfhWiR55BBH6frcLDeYCkEU 9rlLWDNq9K49PM40yHQQ2D5Ck3NlXabGBhob9jxjE8opKO6TKl7VQfpC3rmmoQ== 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=1744832798; 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=7PlVAn8VdvBBO/Q3WAQqKCX/WpAaTMaBKhVYmd5a4dI=; b=kSE0IfgxW0wSfONzPVr4q+dPTXDgtUrT+IXrxV41pTM7zD+cIvY8p5eCdsKi2P/xPJpzFQ qbl9ZLKtD6FPLGM+APjNs9NOS/p4Aj3ZVtObgYRvEY/uuTlgUPeu/Ljg66ewVHpCVCsJYu JH9Aiysl3+6/7NfcvjFoDnUcU7tWUeLcNFUp8kAzC8xD+ehCh1+n4LYgJ5sJPK730AIZuT N/vaJeuLis2bO/JMqH8Ff3UIb2B8x+ybWhmlUDrmO+O1p3fk7/+JAxKO770uLasB3Z1JWw Fb9NVDY+fbwKcoZCTe3iUKDcHUAsZZXUAjt7w43P5NEaQTdg8kc9yG+Xuc8/nw== 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 4ZdBNt3Cb3z2Bp; Wed, 16 Apr 2025 19:46:38 +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 53GJkc9X063963; Wed, 16 Apr 2025 19:46:38 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 53GJkcmT063960; Wed, 16 Apr 2025 19:46:38 GMT (envelope-from git) Date: Wed, 16 Apr 2025 19:46:38 GMT Message-Id: <202504161946.53GJkcmT063960@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Baptiste Daroussin Subject: git: 613310263ae1 - main - timeout(1): Kill self with the same signal that terminated the child 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: bapt X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 613310263ae1f0f65df498dc8e98f460b781946d Auto-Submitted: auto-generated The branch main has been updated by bapt: URL: https://cgit.FreeBSD.org/src/commit/?id=613310263ae1f0f65df498dc8e98f460b781946d commit 613310263ae1f0f65df498dc8e98f460b781946d Author: Aaron LI AuthorDate: 2025-04-03 02:51:06 +0000 Commit: Baptiste Daroussin CommitDate: 2025-04-16 19:45:38 +0000 timeout(1): Kill self with the same signal that terminated the child A shell may not set '$?' to '128 + signal_number' when the process was terminated by a signal. For example, KornShell 93 sets '$?' to '256 + signal_number' in such cases. In order to avoid any possible ambiguity, the POSIX.1-2024 standard requires that timeout mimic the wait status of the child process by terminating itself with the same signal, while disabling core generation. Update the man page accordingly. Obtained-from: DragonFly BSD Reference: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/timeout.html --- bin/timeout/timeout.1 | 51 ++++++++++++++++++++++++--------------------------- bin/timeout/timeout.c | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 29 deletions(-) diff --git a/bin/timeout/timeout.1 b/bin/timeout/timeout.1 index 44525daaec59..43a484dac76f 100644 --- a/bin/timeout/timeout.1 +++ b/bin/timeout/timeout.1 @@ -146,37 +146,33 @@ hours days .El .Sh EXIT STATUS -If the timeout was not reached, the exit status of -.Ar command -is returned. -.Pp -If the timeout was reached and -.Fl -preserve-status -is set, the exit status of -.Ar command -is returned. -If +If the time limit was reached and the .Fl -preserve-status -is not set, an exit status of 124 is returned. -.Pp -If an invalid parameter is passed to -.Fl s -or -.Fl k , -the exit status returned is 125. -.Pp -If +option is not specified, the exit status is 124. +Otherwise, +.Nm +exits with the same exit status as the +.Ar command . +For example, +.Nm +will terminate itself with the same signal if the .Ar command -is an otherwise invalid program, the exit status returned is 126. +is terminated by a signal. .Pp -If +If an error occurred, the following exit values are returned: +.Bl -tag -offset indent with indent -compact +.It 125 +An error other than the two described below occurred. +For example, an invalid duration or signal was specified. +.It 126 +The .Ar command -refers to a non-existing program, the exit status returned is 127. -.Pp -If +was found but could not be executed. +.It 127 +The .Ar command -exits after receiving a signal, the exit status returned is the signal number -plus 128. +could not be found. +.El .Sh EXAMPLES Run .Xr sleep 1 @@ -202,7 +198,8 @@ $ echo $? .Pp Same as above but preserving status. The exit status is 128 + signal number (15 for -.Dv SIGTERM ) : +.Dv SIGTERM ) +for most shells: .Bd -literal -offset indent $ timeout --preserve-status 2 sleep 4 $ echo $? diff --git a/bin/timeout/timeout.c b/bin/timeout/timeout.c index 6e93e9e2911c..e9c4e22fc7d3 100644 --- a/bin/timeout/timeout.c +++ b/bin/timeout/timeout.c @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -239,6 +240,34 @@ set_interval(double iv) err(EXIT_FAILURE, "setitimer()"); } +/* + * In order to avoid any possible ambiguity that a shell may not set '$?' to + * '128+signal_number', POSIX.1-2024 requires that timeout mimic the wait + * status of the child process by terminating itself with the same signal, + * while disabling core generation. + */ +static void __dead2 +kill_self(int signo) +{ + sigset_t mask; + struct rlimit rl; + + /* Reset the signal disposition and make sure it's unblocked. */ + signal(signo, SIG_DFL); + sigfillset(&mask); + sigdelset(&mask, signo); + sigprocmask(SIG_SETMASK, &mask, NULL); + + /* Disable core generation. */ + memset(&rl, 0, sizeof(rl)); + setrlimit(RLIMIT_CORE, &rl); + + logv("killing self with signal %s(%d)", sys_signame[signo], signo); + kill(getpid(), signo); + err(128 + signo, "signal %s(%d) failed to kill self", + sys_signame[signo], signo); +} + int main(int argc, char **argv) { @@ -430,10 +459,12 @@ main(int argc, char **argv) if (timedout && !preserve) { pstat = EXIT_TIMEOUT; } else { + if (WIFSIGNALED(pstat)) + kill_self(WTERMSIG(pstat)); + /* NOTREACHED */ + if (WIFEXITED(pstat)) pstat = WEXITSTATUS(pstat); - else if (WIFSIGNALED(pstat)) - pstat = 128 + WTERMSIG(pstat); } return (pstat);