GNU bug report logs -
#77535
timeout treats very short durations as `0`
Previous Next
To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 77535 in the body.
You can then email your comments to 77535 AT debbugs.gnu.org in the normal way.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
bug-coreutils <at> gnu.org
:
bug#77535
; Package
coreutils
.
(Fri, 04 Apr 2025 16:13:02 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
Nicolas Boichat <nicolas <at> boichat.ch>
:
New bug report received and forwarded. Copy sent to
bug-coreutils <at> gnu.org
.
(Fri, 04 Apr 2025 16:13:02 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
Hi,
Version: timeout (GNU coreutils) 9.6, Archlinux, x86-64.
While playing with different duration parameters to `timeout`, I
noticed that extremely short durations, like `1e-3000`, are rounded
down to `0`. The problem is that `0` has a special meaning (disabling
the timeout), so I don't think this is desired.
All of these commands exit immediately:
```
timeout 0.0001 cat
timeout 1e-100 cat
timeout 1e-300 cat
timeout 1e-323 cat
```
But these never exits:
```
timeout 1e-324 cat
timeout 1e-3000 cat
```
As if we had typed:
```
timeout 0 cat
```
I think there is some logic in `printf` to handle float parsing
underflow, so maybe this can be reused in `timeout` as well.
Thanks,
Reply sent
to
Pádraig Brady <P <at> draigBrady.com>
:
You have taken responsibility.
(Fri, 04 Apr 2025 19:29:02 GMT)
Full text and
rfc822 format available.
Notification sent
to
Nicolas Boichat <nicolas <at> boichat.ch>
:
bug acknowledged by developer.
(Fri, 04 Apr 2025 19:29:02 GMT)
Full text and
rfc822 format available.
Message #10 received at 77535-done <at> debbugs.gnu.org (full text, mbox):
On 04/04/2025 16:26, Nicolas Boichat wrote:
> Hi,
>
> Version: timeout (GNU coreutils) 9.6, Archlinux, x86-64.
>
> While playing with different duration parameters to `timeout`, I
> noticed that extremely short durations, like `1e-3000`, are rounded
> down to `0`. The problem is that `0` has a special meaning (disabling
> the timeout), so I don't think this is desired.
>
> All of these commands exit immediately:
> ```
> timeout 0.0001 cat
> timeout 1e-100 cat
> timeout 1e-300 cat
> timeout 1e-323 cat
> ```
>
> But these never exits:
> ```
> timeout 1e-324 cat
> timeout 1e-3000 cat
> ```
>
> As if we had typed:
> ```
> timeout 0 cat
> ```
>
> I think there is some logic in `printf` to handle float parsing
> underflow, so maybe this can be reused in `timeout` as well.
The following should avoid this issue.
Marking this as done.
thanks!
Pádraig
diff --git a/src/timeout.c b/src/timeout.c
index 578d71070..6756cd888 100644
--- a/src/timeout.c
+++ b/src/timeout.c
@@ -371,6 +371,10 @@ parse_duration (char const *str)
usage (EXIT_CANCELED);
}
+ /* Clamp underflow to 1ns, as 0 disables the timeout. */
+ if (duration == 0 && errno == ERANGE)
+ duration = 1e-9;
+
return duration;
}
Information forwarded
to
bug-coreutils <at> gnu.org
:
bug#77535
; Package
coreutils
.
(Sat, 05 Apr 2025 05:41:03 GMT)
Full text and
rfc822 format available.
Message #13 received at 77535-done <at> debbugs.gnu.org (full text, mbox):
On Fri, 4 Apr 2025 at 21:27, Pádraig Brady <P <at> draigbrady.com> wrote:
>
> On 04/04/2025 16:26, Nicolas Boichat wrote:
> > Hi,
> >
> > Version: timeout (GNU coreutils) 9.6, Archlinux, x86-64.
> >
> > While playing with different duration parameters to `timeout`, I
> > noticed that extremely short durations, like `1e-3000`, are rounded
> > down to `0`. The problem is that `0` has a special meaning (disabling
> > the timeout), so I don't think this is desired.
> >
> > All of these commands exit immediately:
> > ```
> > timeout 0.0001 cat
> > timeout 1e-100 cat
> > timeout 1e-300 cat
> > timeout 1e-323 cat
> > ```
> >
> > But these never exits:
> > ```
> > timeout 1e-324 cat
> > timeout 1e-3000 cat
> > ```
> >
> > As if we had typed:
> > ```
> > timeout 0 cat
> > ```
> >
> > I think there is some logic in `printf` to handle float parsing
> > underflow, so maybe this can be reused in `timeout` as well.
>
> The following should avoid this issue.
>
> Marking this as done.
That was fast! Thanks!
>
> thanks!
> Pádraig
>
> diff --git a/src/timeout.c b/src/timeout.c
> index 578d71070..6756cd888 100644
> --- a/src/timeout.c
> +++ b/src/timeout.c
> @@ -371,6 +371,10 @@ parse_duration (char const *str)
> usage (EXIT_CANCELED);
> }
>
> + /* Clamp underflow to 1ns, as 0 disables the timeout. */
> + if (duration == 0 && errno == ERANGE)
> + duration = 1e-9;
> +
> return duration;
> }
>
Information forwarded
to
bug-coreutils <at> gnu.org
:
bug#77535
; Package
coreutils
.
(Sat, 05 Apr 2025 08:04:01 GMT)
Full text and
rfc822 format available.
Message #16 received at 77535 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
On 2025-04-04 12:27, Pádraig Brady wrote:
> + /* Clamp underflow to 1ns, as 0 disables the timeout. */
> + if (duration == 0 && errno == ERANGE)
> + duration = 1e-9;
That isn't exactly right as the 1e-9 double-rounds to 2e-9 when we
compute the struct timespec. Also, even with the patch the code
mishandles 16777216.000000001 (2**24 + 10**-9) by treating it as if it
were just 16777216. These are tiny bugs, I know, but I took up the
challenge of doing this things more correctly by installing the attached.
[0001-timeout-round-timeouts-up.patch (text/x-patch, attachment)]
Information forwarded
to
bug-coreutils <at> gnu.org
:
bug#77535
; Package
coreutils
.
(Sat, 05 Apr 2025 11:04:02 GMT)
Full text and
rfc822 format available.
Message #19 received at 77535 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
On 05/04/2025 09:03, Paul Eggert wrote:
> On 2025-04-04 12:27, Pádraig Brady wrote:
>> + /* Clamp underflow to 1ns, as 0 disables the timeout. */
>> + if (duration == 0 && errno == ERANGE)
>> + duration = 1e-9;
>
> That isn't exactly right as the 1e-9 double-rounds to 2e-9 when we
> compute the struct timespec. Also, even with the patch the code
> mishandles 16777216.000000001 (2**24 + 10**-9) by treating it as if it
> were just 16777216. These are tiny bugs, I know, but I took up the
> challenge of doing this things more correctly by installing the attached.
This is the first time coreutils is linking with libm.
So practically that does add measurable overhead:
$ time seq 10000 | xargs -n1 src/timeout-old >/dev/null
real 0m7.139s
$ time seq 10000 | xargs -n1 src/timeout >/dev/null
real 0m8.161s
So on my 2.6GHz i7-5600U we're adding 102,200 ns to the startup time,
to address theoretical single nanosecond issues.
Given the code is also more complex, I'm thinking using libm is not worth it?
BTW I'll apply the attached cleanups if we keep the libm dependency.
cheers,
Pádraig
[timeout-round-tweaks.patch (text/x-patch, attachment)]
Information forwarded
to
bug-coreutils <at> gnu.org
:
bug#77535
; Package
coreutils
.
(Sat, 05 Apr 2025 18:03:02 GMT)
Full text and
rfc822 format available.
Message #22 received at 77535 <at> debbugs.gnu.org (full text, mbox):
I was interested to see that the code makes uses of strtod, and how this interacts with the minute / hour / day suffix.
$ strace -e trace=clock_nanosleep sleep 3
clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=3, tv_nsec=0},
$ strace -e trace=clock_nanosleep sleep 0xas
clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=10, tv_nsec=0},
$ strace -e trace=clock_nanosleep sleep 0xam
clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=600, tv_nsec=0},
$ strace -e trace=clock_nanosleep sleep 0xad
clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=173, tv_nsec=0},
Here 0xad is interpreted as 173 seconds, not 10 days.
It's a corner case, but should sleep(1) support or tolerate hex input, and if so, how should it handle the "d" suffix? FWIW I'd just vote to return an error for hex intervals.
Cheers,
Phil
Information forwarded
to
bug-coreutils <at> gnu.org
:
bug#77535
; Package
coreutils
.
(Sat, 05 Apr 2025 18:46:02 GMT)
Full text and
rfc822 format available.
Message #25 received at 77535 <at> debbugs.gnu.org (full text, mbox):
On 05/04/2025 19:02, Philip Rowlands wrote:
> I was interested to see that the code makes uses of strtod, and how this interacts with the minute / hour / day suffix.
>
> $ strace -e trace=clock_nanosleep sleep 3
> clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=3, tv_nsec=0},
>
> $ strace -e trace=clock_nanosleep sleep 0xas
> clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=10, tv_nsec=0},
>
> $ strace -e trace=clock_nanosleep sleep 0xam
> clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=600, tv_nsec=0},
>
> $ strace -e trace=clock_nanosleep sleep 0xad
> clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=173, tv_nsec=0},
>
> Here 0xad is interpreted as 173 seconds, not 10 days.
>
> It's a corner case, but should sleep(1) support or tolerate hex input, and if so, how should it handle the "d" suffix? FWIW I'd just vote to return an error for hex intervals.
Good point :)
Given FreeBSD and ksh sleep implementations also behave like GNU,
we should probably just document the edge case that
(day) suffixes are best avoided with hex inputs.
~$ ksh
$ type sleep
sleep is a shell builtin
$ time sleep 0x10d
real 4m29.00s
cheers,
Pádraig
Information forwarded
to
bug-coreutils <at> gnu.org
:
bug#77535
; Package
coreutils
.
(Sat, 05 Apr 2025 19:43:02 GMT)
Full text and
rfc822 format available.
Message #28 received at 77535 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
On 05/04/2025 19:45, Pádraig Brady wrote:
> On 05/04/2025 19:02, Philip Rowlands wrote:
>> I was interested to see that the code makes uses of strtod, and how this interacts with the minute / hour / day suffix.
>>
>> $ strace -e trace=clock_nanosleep sleep 3
>> clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=3, tv_nsec=0},
>>
>> $ strace -e trace=clock_nanosleep sleep 0xas
>> clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=10, tv_nsec=0},
>>
>> $ strace -e trace=clock_nanosleep sleep 0xam
>> clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=600, tv_nsec=0},
>>
>> $ strace -e trace=clock_nanosleep sleep 0xad
>> clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=173, tv_nsec=0},
>>
>> Here 0xad is interpreted as 173 seconds, not 10 days.
>>
>> It's a corner case, but should sleep(1) support or tolerate hex input, and if so, how should it handle the "d" suffix? FWIW I'd just vote to return an error for hex intervals.
>
> Good point :)
> Given FreeBSD and ksh sleep implementations also behave like GNU,
> we should probably just document the edge case that
> (day) suffixes are best avoided with hex inputs.
>
> ~$ ksh
> $ type sleep
> sleep is a shell builtin
> $ time sleep 0x10d
> real 4m29.00s
I'll apply the attached later to document this.
cheers,
Pádraig
[coreutils-hex-duration-suffixes.patch (text/x-patch, attachment)]
Information forwarded
to
bug-coreutils <at> gnu.org
:
bug#77535
; Package
coreutils
.
(Sat, 05 Apr 2025 20:58:02 GMT)
Full text and
rfc822 format available.
Message #31 received at 77535 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
On 05/04/2025 12:03, Pádraig Brady wrote:
> On 05/04/2025 09:03, Paul Eggert wrote:
>> On 2025-04-04 12:27, Pádraig Brady wrote:
>>> + /* Clamp underflow to 1ns, as 0 disables the timeout. */
>>> + if (duration == 0 && errno == ERANGE)
>>> + duration = 1e-9;
>>
>> That isn't exactly right as the 1e-9 double-rounds to 2e-9 when we
>> compute the struct timespec. Also, even with the patch the code
>> mishandles 16777216.000000001 (2**24 + 10**-9) by treating it as if it
>> were just 16777216. These are tiny bugs, I know, but I took up the
>> challenge of doing this things more correctly by installing the attached.
>
> This is the first time coreutils is linking with libm.
> So practically that does add measurable overhead:
>
> $ time seq 10000 | xargs -n1 src/timeout-old >/dev/null
> real 0m7.139s
>
> $ time seq 10000 | xargs -n1 src/timeout >/dev/null
> real 0m8.161s
>
> So on my 2.6GHz i7-5600U we're adding 102,200 ns to the startup time,
> to address theoretical single nanosecond issues.
> Given the code is also more complex, I'm thinking using libm is not worth it?
>
> BTW I'll apply the attached cleanups if we keep the libm dependency.
I'm going to apply the attached later to remove the libm dependency.
It's just too much of a dependency for minimal functionality.
All existing tests are maintained, and still pass.
cheers,
Pádraig
[timeout-remove-libm.patch (text/x-patch, attachment)]
Information forwarded
to
bug-coreutils <at> gnu.org
:
bug#77535
; Package
coreutils
.
(Mon, 07 Apr 2025 08:09:02 GMT)
Full text and
rfc822 format available.
Message #34 received at 77535 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
On 2025-04-05 13:56, Pádraig Brady wrote:
> I'm going to apply the attached later to remove the libm dependency.
> It's just too much of a dependency for minimal functionality.
Thanks, agreed about the dependency. Still, 'timeout' (and, now that I
think about it, 'sleep' and 'tail') should always wait for at least the
time requested.
After thinking about it I installed the attached further patch, which
addresses the problem in a different way without needing libm on
GNU/Linux. Although we could tighten the bounds further in typical cases
(by using the algorithm 'date' uses to parse seconds, if the string is
of that form) I tried to keep it simple, as the main point is to not
sleep for less than the time requested.
Floating point can be such a pain sometimes, even for simple things.
(Read the cited paper and see....)
[0001-timeout-don-t-sleep-less-than-requested.patch (text/x-patch, attachment)]
Information forwarded
to
bug-coreutils <at> gnu.org
:
bug#77535
; Package
coreutils
.
(Mon, 07 Apr 2025 08:24:01 GMT)
Full text and
rfc822 format available.
Message #37 received at 77535 <at> debbugs.gnu.org (full text, mbox):
On 2025-04-05 12:41, Pádraig Brady wrote:
> +Note it's best to avoid combining suffixes with hexadecimal arguments,
> +as any @samp{d} will @emph{not} be interpreted as a suffix.
But 'd' is interpreted as a suffix with hexadecimal arguments that have
an exponent. For example, 'sleep 0x1p0d' sleeps for 1 day. (Also, "Note"
isn't needed.) Perhaps change to:
A hexadecimal number can precede a @samp{d} suffix only if the number
has a @samp{p} style exponent, e.g., @samp{0x1p0d} means one day.
Information forwarded
to
bug-coreutils <at> gnu.org
:
bug#77535
; Package
coreutils
.
(Mon, 07 Apr 2025 17:46:02 GMT)
Full text and
rfc822 format available.
Message #40 received at 77535 <at> debbugs.gnu.org (full text, mbox):
On 07/04/2025 09:23, Paul Eggert wrote:
> On 2025-04-05 12:41, Pádraig Brady wrote:
>> +Note it's best to avoid combining suffixes with hexadecimal arguments,
>> +as any @samp{d} will @emph{not} be interpreted as a suffix.
>
> But 'd' is interpreted as a suffix with hexadecimal arguments that have
> an exponent. For example, 'sleep 0x1p0d' sleeps for 1 day. (Also, "Note"
> isn't needed.) Perhaps change to:
>
> A hexadecimal number can precede a @samp{d} suffix only if the number
> has a @samp{p} style exponent, e.g., @samp{0x1p0d} means one day.
Cool,
It's better to document a workaround than a restriction.
I pushed the above adjustment in your name.
cheers,
Pádraig
Information forwarded
to
bug-coreutils <at> gnu.org
:
bug#77535
; Package
coreutils
.
(Mon, 07 Apr 2025 17:47:02 GMT)
Full text and
rfc822 format available.
Message #43 received at 77535 <at> debbugs.gnu.org (full text, mbox):
On 07/04/2025 09:08, Paul Eggert wrote:
> On 2025-04-05 13:56, Pádraig Brady wrote:
>> I'm going to apply the attached later to remove the libm dependency.
>> It's just too much of a dependency for minimal functionality.
>
> Thanks, agreed about the dependency. Still, 'timeout' (and, now that I
> think about it, 'sleep' and 'tail') should always wait for at least the
> time requested.
>
> After thinking about it I installed the attached further patch, which
> addresses the problem in a different way without needing libm on
> GNU/Linux. Although we could tighten the bounds further in typical cases
> (by using the algorithm 'date' uses to parse seconds, if the string is
> of that form) I tried to keep it simple, as the main point is to not
> sleep for less than the time requested.
>
> Floating point can be such a pain sometimes, even for simple things.
> (Read the cited paper and see....)
Nice.
I hadn't realized gnulib's signbit avoided the dependency on libm.
thanks!
Pádraig
bug archived.
Request was from
Debbugs Internal Request <help-debbugs <at> gnu.org>
to
internal_control <at> debbugs.gnu.org
.
(Tue, 06 May 2025 11:24:13 GMT)
Full text and
rfc822 format available.
This bug report was last modified 30 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.