Commit graph

22 commits

Author SHA1 Message Date
Konstantin Belousov
81ef001250 timeout(1): pass full 32bit error return code from the exited child
Switch to use waitid(2) to receive siginfo_t with the complete error
code from the exited process.

Tested by:	pho
Reviewed by:	markj
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D50752
2025-06-10 02:52:34 +03:00
Konstantin Belousov
aa8cdb7cae timeout(1): only start the child command after the parent is fully set up
Since the default disposition for SIGCHLD is ignore, the prematurely
exited child would cause SIGCHLD dropped.  This makes timeout(1) hang,
because REAP_STATUS reports a zombie not waited for, but SIGCHLD for it
was already lost, so the main loop cannot exit, instead calling into
sigsuspend().

Reported and tested by:	pho
Reviewed by:	markj
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D50752
2025-06-10 02:51:19 +03:00
Konstantin Belousov
bff05e8a8c timeout(1): print errno when signalling syscalls failed
Tested by:	pho
Reviewed by:	markj
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D50752
2025-06-10 02:51:13 +03:00
Konstantin Belousov
15e4b8d5ef timeout(1): silence warnings for ESRCH
It is possible for the child to become zombie and then there is nothing
to signal.

Reported and tested by:	pho
Reviewed by:	markj
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D50752
2025-06-10 02:51:06 +03:00
Aaron LI
613310263a 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
2025-04-16 21:45:38 +02:00
Aaron LI
844cef26e8 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
2025-04-16 21:45:38 +02:00
Aaron LI
2390cbfe55 timeout(1): Fix the inheritance of signal dispositions
POSIX.1-2024 requires that the child process inherit the same signal
dispositions as the timeout(1) utility inherited, except for the signal
to be sent upon timeout.

For example, when timeout(1) is run by nohup(1), the command should be
protected from SIGHUP.

Obtained-from: DragonFly BSD
2025-04-16 21:45:38 +02:00
Aaron LI
8e1d9fe066 timeout(1): Improve to show more verbose log messages 2025-04-16 21:45:38 +02:00
Aaron LI
aae3eb24df timeout(1): Fix the handling of repeated terminating signals
This actually fixes the following two issues:

* If a terminating signal (e.g., HUP/INT/TERM) was received, timeout
  would propagate it to the command and then ignore it.  So it was
  unable to resend the same terminating signal to the command.  This was
  different from the GNU's timeout(1), and also contradicted the
  POSIX.1-2024 standard.

* Sending two different terminating signals would break timeout(1)'s
  --kill-after mechanism.  That was because the second signal would
  break the for() loop, so the second SIGALRM set by '--kill-after'
  would never be caught.

  For example, in one shell run:
  $ time timeout -f -v -s INT -k 1 2 sh -T -c \
        'trap date INT HUP; sleep 5; echo ok; date'
  and in another shell run:
  $ pkill -INT timeout; pkill -HUP timeout
  in the end, the time(1) would report it cost 5 seconds instead of the
  expected 3 seconds.

Obtained-from: DragonFly BSD
2025-04-16 21:45:38 +02:00
Aaron LI
06c74693c2 timeout(1): Also send SIGCONT because the child may be stopped
The POSIX.1-2024 says:

"If the subsequent wait status of the child process shows that it was
stopped by a signal, a SIGCONT signal shall also be sent in the same
manner as the first signal; otherwise, a SIGCONT signal may be sent in
the same manner."

As it's allowed by the standard, we just always send the SIGCONT signal
to the child process regardless of its stop state, so that timeout could
terminate a stopped child.

Obtained-from: DragonFly BSD
Reference: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/timeout.html
2025-04-16 21:45:38 +02:00
Aaron LI
086f178536 timeout(1): Enhance send_sig() and prepare for later updates
Enhance send_sig() to better encapsulate the signal sending for
both foreground and non-foreground modes.  This also fixes the issue
that the latter mode was missing verbose messages.

In addition, improve the verbose logging for signals.

Obtained-from: DragonFly BSD
2025-04-16 21:45:38 +02:00
Aaron LI
8a9927ecd4 timeout(1): Add -f and -p options as per POSIX.1-2024
POSIX.1-2024 first defined the timeout(1) utility and specified the '-f'
and '-p' options, which are the short versions of '--foreground' and
'--preserve-status' options, respectively.  Add the short versions to
comply with the Standard.

Obtained-from: DragonFly BSD
Reference: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/timeout.html
2025-04-16 21:45:38 +02:00
Aaron LI
c5cdc13045 timeout(1): Handle sig_alrm and sig_term together to dedup code
Merge the 'sig_alrm' and 'sig_term' conditionals, and thus reduce some
duplicate code.

Obtained-from: DragonFly BSD
2025-04-16 21:45:38 +02:00
Aaron LI
790e361736 timeout(1): Multiple minor tweaks and cleanups 2025-04-16 21:45:38 +02:00
Aaron LI
92f8006e89 timeout(1): sig_atomic_t variables must also be 'volatile'
Obtained-from: OpenBSD (via DragonFly BSD)
2025-04-16 21:45:38 +02:00
Aaron LI
35503fe28e timeout(1): Use _exit(2) instead of err() in child if exec failed
* The child should _exit(2) instead of calling exit(3) via err(3) if the
  execvp() failed.
* execvp(2) does not return except on error, so there is no need to
  check if the return value is -1.

Obtained-from: OpenBSD (via DragonFly BSD)
2025-04-16 21:45:38 +02:00
Aaron LI
e7bf1e5f1d timeout(1): Improve duration parsing and error messages
Obtained-from: OpenBSD (via DragonFly BSD)
2025-04-16 21:45:37 +02:00
Gordon Bergling
d633a7d121 timeout(1): Add -v/--verbose option to show diagnosis info
The -v/--verbose option enables this utility to show diagnosis
info to stderr about any signal sent on timeout.

This implementation refers to GNU coreutils's timeout(1).

Reviewed by:	bapt, Alexander Ziaee (manpages)
Approved by:	bapt (src)
Obtained from:	DragonFlyBSD
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D48225
2025-01-04 09:52:56 +01:00
Gordon Bergling
06690044da timeout(1): Some minor tweaks and improvements
- Define exit status and macros and use them
- Improve the second kill logic by setting 'do_second_kill = false'
  after configuring the second kill
- Minor style tweaks
- Reorder options in the man page, as well as the usage help
- Reorder the exit status in the man page
- Enhance the HISTORY section in the man page (obtained from NetBSD)

Reviewed by:	bapt, Alexander Ziaee (manpages)
Approved by:	bapt (src)
Obtained from:	DragonFlyBSD
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D47866
2024-12-28 08:13:22 +01:00
rilysh
4d8d9111a4 bin/timeout: remove unreachable break after usage()
Signed-off-by: rilysh <nightquick@proton.me>
Reviewed by: imp
Pull Request: https://github.com/freebsd/freebsd-src/pull/872
2024-01-03 12:05:50 -07:00
Warner Losh
1d386b48a5 Remove $FreeBSD$: one-line .c pattern
Remove /^[\s*]*__FBSDID\("\$FreeBSD\$"\);?\s*\n/
2023-08-16 11:54:42 -06:00
Mateusz Piotrowski
e7ab133648 timeout: Move from /usr/bin to /bin
timeout(1) is used by /etc/rc.d/zfskeys. Unfortunately, having
timeout(1) installed in /usr/bin causes problems when /usr is an
encrypted ZFS partition.

Implementing timeout(1) in sh(1) is not trivial. A more elegant solution
is to move timeout(1) to /bin so that it is available to early services
in the boot process.

PR:		265221
Reviewed by:	allanjude, des, imp
Approved by:	allanjude, des, imp
Reported by:	Ivan <r4@sovserv.ru>
Fixes:	33ff39796f Add zfskeys rc.d script for auto-loading encryption keys
MFC after:	1 week
Relnotes:	yes
Sponsored by:	Modirum MDPay
Sponsored by:	Klara Inc.
Differential Revision:	https://reviews.freebsd.org/D38344
2023-02-02 18:34:35 +01:00
Renamed from usr.bin/timeout/timeout.c (Browse further)