From nobody Wed Apr 16 19:46:37 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 4ZdBNt1gcnz5t8jY; 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 4ZdBNs2kNmz3l18; Wed, 16 Apr 2025 19:46:37 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1744832797; 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=JPcrJJQxCBsvwusN5oTgcMpraiFuFt2gGNHXfiySBmA=; b=cyVcz/MXWXevzyUJ0OZ8tq/sSAKeCiSCdpt18tUgjbKB+DzyiIJouBJSzi/uxhQykmb+xR 0xUZtewRjI2QHFovkBSW5nBnfCVcWhbr6bKxnGbWDxp8Vx9C9/PlhCt7qiR/D85giV/+om VEQfe9RFmAbwUFfz6JZi2uyGAOBNAMebIk9iRBkfksdGZjobJLljEM3CI9PddtmRefJ8jD 9VQTJGKjPBye8KGfyw45s4HbC3UXEjvDa5/qC6Py2WTK9nVrN7HeHH3UKTRlUElnizidWg ov82bdr2sqgb9MN1JLyR045lyDIcPO5mC8iyhqCFHm9JdKcOEKexWO98AtT8lw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1744832797; a=rsa-sha256; cv=none; b=C48TWnJaZFAYMWlGha1fG2YyyIWk8on+zUMgQxOcAb6GTiLT+kG0eoe0gYvVBaGp+3+j4B SXGKcOJsi1HpXLH0snW9IOASI1bpkZoc9Wjcdya8cFDYtR2Vb9TldS/Uvu9qtWYmF4BwUD vR69PnG1CKOzk57VbOiXffu/UJ2/nrT+e3Ak+b/AJBjfjhE2L4THbX59bMOo9OvfsA2Ag1 8dcWKGHwkf8TkcEZkiFfN18iF1mzAg8VKZqCWkHc7g3u1tf3v8xga3mc1l1FUpF/2oKU++ Ia8+JRNTVT4sGwBDWcjdNxJK94NHiRDU4pvZmadgypj4wkd1qI0sLTF6De9Sgg== 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=1744832797; 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=JPcrJJQxCBsvwusN5oTgcMpraiFuFt2gGNHXfiySBmA=; b=dzYj+Z6eP0tsK9Jk78hfuUR7mYAqX0GU13i1IosZ9uIcItW+6IHORmn3obUsPN9xcf23tr v+jeyOF/RIHsfvuZp0ouWenSJnLnutXFHjkDTPD3+A/Cx/sN76rODCUewPsXGCfR+FWEAj SI789sSp4nPjz09TqqF87mt1ycEOxuQnp7YE/bXt1xIiGvojaMAIN1utYsyOlDhtvWJ5vL /yuq0iG71bzERcYIsnt9s56nUU9FM3G2rKE3svcP1U8IJvNWF05/daXih1HG7Bzfso2KlD NDOoenamVtVmtlK9JzHXFhbAauBLf8t7guEg5pRuXxw96k7pEsvt0txp2Gm9qg== 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 4ZdBNs2DGlz2Fx; Wed, 16 Apr 2025 19:46:37 +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 53GJkbHs063923; Wed, 16 Apr 2025 19:46:37 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 53GJkbJM063920; Wed, 16 Apr 2025 19:46:37 GMT (envelope-from git) Date: Wed, 16 Apr 2025 19:46:37 GMT Message-Id: <202504161946.53GJkbJM063920@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: 844cef26e810 - main - timeout(1): Catch all signals and propagate them 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: bapt X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 844cef26e810d903e11bf83cc6f6fd2e22a299f1 Auto-Submitted: auto-generated The branch main has been updated by bapt: URL: https://cgit.FreeBSD.org/src/commit/?id=844cef26e810d903e11bf83cc6f6fd2e22a299f1 commit 844cef26e810d903e11bf83cc6f6fd2e22a299f1 Author: Aaron LI AuthorDate: 2025-04-03 01:20:01 +0000 Commit: Baptiste Daroussin CommitDate: 2025-04-16 19:45:38 +0000 timeout(1): Catch all signals and propagate them The POSIX.1-2024 standard requires that timeout(1) utility propagate all signals except SIGALRM, so timeout(1) needs to catch all signals for this purpose. In addition, we need to separate those signals whose default action is to terminate the program, because timeout(1) should start the second timer for the kill signal if those signals are received. Obtained-from: DragonFly BSD Reference: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/timeout.html --- bin/timeout/timeout.1 | 22 ++++++++++++ bin/timeout/timeout.c | 92 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 79 insertions(+), 35 deletions(-) diff --git a/bin/timeout/timeout.1 b/bin/timeout/timeout.1 index 371a167d19f3..44525daaec59 100644 --- a/bin/timeout/timeout.1 +++ b/bin/timeout/timeout.1 @@ -73,6 +73,28 @@ inherited, except for the signal that will be sent upon timeout, which is reset to take the default action and should terminate the process. .Pp +If +.Nm +receives the +.Dv SIGALRM +signal, it will behave as if the time limit has been reached +and send the specified signal to +.Ar command . +For any other signals delivered to +.Nm , +it will propagate them to +.Ar command , +with the exception of +.Dv SIGKILL +and +.Dv SIGSTOP . +If you want to prevent the +.Ar command +from being timed out, send +.Dv SIGKILL +to +.Nm . +.Pp The options are as follows: .Bl -tag -width indent .It Fl f , Fl -foreground diff --git a/bin/timeout/timeout.c b/bin/timeout/timeout.c index 1c4cfa6e017d..6e93e9e2911c 100644 --- a/bin/timeout/timeout.c +++ b/bin/timeout/timeout.c @@ -1,6 +1,7 @@ /*- * Copyright (c) 2014 Baptiste Daroussin * Copyright (c) 2014 Vsevolod Stakhov + * Copyright (c) 2025 Aaron LI * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,8 +48,10 @@ #define EXIT_CMD_NOENT 127 static volatile sig_atomic_t sig_chld = 0; -static volatile sig_atomic_t sig_term = 0; static volatile sig_atomic_t sig_alrm = 0; +static volatile sig_atomic_t sig_term = 0; /* signal to terminate children */ +static volatile sig_atomic_t sig_other = 0; /* signal to propagate */ +static int killsig = SIGTERM; /* signal to kill children */ static const char *command = NULL; static bool verbose = false; @@ -137,19 +140,46 @@ parse_signal(const char *str) static void sig_handler(int signo) { - switch (signo) { - case SIGINT: - case SIGHUP: - case SIGQUIT: - case SIGTERM: + if (signo == killsig) { sig_term = signo; - break; + return; + } + + switch (signo) { case SIGCHLD: sig_chld = 1; break; case SIGALRM: sig_alrm = 1; break; + case SIGHUP: + case SIGINT: + case SIGQUIT: + case SIGILL: + case SIGTRAP: + case SIGABRT: + case SIGEMT: + case SIGFPE: + case SIGBUS: + case SIGSEGV: + case SIGSYS: + case SIGPIPE: + case SIGTERM: + case SIGXCPU: + case SIGXFSZ: + case SIGVTALRM: + case SIGPROF: + case SIGUSR1: + case SIGUSR2: + /* + * Signals with default action to terminate the process. + * See the sigaction(2) man page. + */ + sig_term = signo; + break; + default: + sig_other = signo; + break; } } @@ -214,8 +244,6 @@ main(int argc, char **argv) { int ch, status, sig; int pstat = 0; - int killsig = SIGTERM; - size_t i; pid_t pid, cpid; double first_kill; double second_kill = 0; @@ -225,17 +253,8 @@ main(int argc, char **argv) bool do_second_kill = false; bool child_done = false; sigset_t zeromask, allmask, oldmask; - struct sigaction signals; + struct sigaction sa; struct procctl_reaper_status info; - int signums[] = { - -1, - SIGTERM, - SIGINT, - SIGHUP, - SIGCHLD, - SIGALRM, - SIGQUIT, - }; const char optstr[] = "+fhk:ps:v"; const struct option longopts[] = { @@ -316,22 +335,17 @@ main(int argc, char **argv) /* parent continues here */ - memset(&signals, 0, sizeof(signals)); - sigemptyset(&signals.sa_mask); - - if (killsig != SIGKILL && killsig != SIGSTOP) - signums[0] = killsig; - - for (i = 0; i < sizeof(signums) / sizeof(signums[0]); i++) - sigaddset(&signals.sa_mask, signums[i]); - - signals.sa_handler = sig_handler; - signals.sa_flags = SA_RESTART; - - for (i = 0; i < sizeof(signums) / sizeof(signums[0]); i++) { - if (signums[i] > 0 && - sigaction(signums[i], &signals, NULL) == -1) - err(EXIT_FAILURE, "sigaction()"); + /* Catch all signals in order to propagate them. */ + memset(&sa, 0, sizeof(sa)); + sigfillset(&sa.sa_mask); + sa.sa_handler = sig_handler; + sa.sa_flags = SA_RESTART; + for (sig = 1; sig < sys_nsig; sig++) { + if (sig == SIGKILL || sig == SIGSTOP || sig == SIGCONT || + sig == SIGTTIN || sig == SIGTTOU) + continue; + if (sigaction(sig, &sa, NULL) == -1) + err(EXIT_FAILURE, "sigaction(%d)", sig); } /* Don't stop if background child needs TTY */ @@ -399,6 +413,14 @@ main(int argc, char **argv) do_second_kill = false; killsig = SIGKILL; } + + } else if (sig_other) { + /* Propagate any other signals. */ + sig = sig_other; + sig_other = 0; + logv("received signal %s(%d)", sys_signame[sig], sig); + + send_sig(pid, sig, foreground); } }