Subject: Re: bug#70219: Bug/Issue with timeout and signals

From: "Branden R. Williams" <[email-masked]>
Date: Sat, 6 Apr 2024 10:50:38 -0500

Working from the code published here: https://github.com/coreutils/coreutils/blob/master/src/timeout.c

If you look at the code, you can see the kill_after variable set on line 486 if the switch is there. In the cleanup() function on line 202, it looks for that variable to be st on line 212, then sets the kill signal to be SIGKILL and sets the timeout. But on line 578, the timeout is overridden anyway by the timeout variable obtained from the argv on line 520. So as I stated previously, if the goal of the -k is to send SIGKILL, it should not be a kill_after or require any seconds to be sent. What is happening on line 485 is it is capturing what SHOULD be the duration passed to “timeout” to kill_after, and then the timeout that is attempted to be grabbed in line 520 is literally the command you are wanting to run the timeout against.

It does not appear to matter what you pass into -k as it is never used in practice. -k does not do this:

  -k, --kill-after=DURATION
                 also send a KILL signal if COMMAND is still running
                   this long after the initial signal was sent

It’s a logic bug. The -k flag should not take a duration, but just set the kill signal to SIGKILL. See this example where the 2s is captured on line 486 leaving nothing for line 520.

$ timeout -k 2s ping 8.8.8.8
timeout: invalid time interval ‘ping’
Try 'timeout --help' for more information.

See these examples of passing garbage into the -k flag:

$ timeout -k 2s 2s ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=114 time=2.02 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=114 time=1.92 ms

$ timeout -k 32s 2s ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=114 time=2.37 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=114 time=1.94 ms

$ timeout -k 92s 2s ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=114 time=1.94 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=114 time=8.38 ms

$ timeout -k 9265535s 2s ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=114 time=8.77 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=114 time=11.8 ms

$ timeout 2s ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=114 time=1.94 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=114 time=2.00 ms

Regards,

B

> On Apr 6, 2024, at 9:44 AM, Chris Elvidge <[email-masked]> wrote:
> 
> Branden,
> 
> Then how come timeout -k 10s 20s ping 8.8.8.8 works?
> 10s is DEFINITELY NOT an integer. 20s in the timeout value.
> 
> I still think your reasoning is suspect.
> 
> 
> On 06/04/2024 at 13:43, Branden R. Williams wrote:
>> I understand this, but the manpage and the help file do not explain the functionally this way. The manpage suggests that the following should work:
>> $ timeout -k 10s sleep 10
>> It does not because the first argument after -k MUST be the an integer value of the signal you want to send, not the duration that the manpage and --help tell you to pass.
>> Regards,
>> B
>>> On Apr 6, 2024, at 4:06 AM, Andreas Schwab <[email-masked]> wrote:
>>> 
>>> On Apr 05 2024, "Branden R. Williams" via GNU coreutils Bug Reports wrote:
>>> 
>>>> That’s not an accurate representation of what the command actually does. The argument after -k MUST be the kill signal code, without the code the command fails. The manpage and help document agree with what you are saying but the execution of the program fails.
>>> 
>>> $ timeout -k USR1 1s sleep 10
>>> timeout: invalid time interval ‘USR1’
>>> Try 'timeout --help' for more information.
>>> $ timeout -s KILL 1s sleep 10
>>> Killed
>>> 
>>> -- 
>>> Andreas Schwab, [email-masked]
>>> GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
>>> "And now for something completely different."
> 
> 
> -- 
> 
> Chris Elvidge
> 
> 5 Ebor Park, Appleton Roebuck, York, Nor