Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

GNU sleep's "infinity" parameter

169 views
Skip to first unread message

Kenny McCormack

unread,
Apr 9, 2018, 3:22:53 AM4/9/18
to
Every so often, in a shell script or whatever, one needs to sleep (pause)
"forever". Usually, what you do is something like: sleep <verybignumber>
and that is usually sufficient.

However, in fact, GNU sleep can be called with a parameter of "infinity",
which, it seems, does really sleep "forever". Note, BTW, that Perl has a
similar functionality (calling it's 'sleep' function with no parameter):

$ perl -e sleep

Anyway, back to "GNU sleep", I was curious as to how "infinity" was
actually implemented and was a bit surprised by what I found.

$ strace sleep infinity
(lots of stuff, ending with)
munmap(0x7f0e4f66e000, 81202) = 0
brk(NULL) = 0x178e000
brk(0x17af000) = 0x17af000
nanosleep({2073600, 999999999},

Which leads to the question: What is 2073600???

Observe:
$ date -d '2073600 seconds'
Thu May 3 01:17:52 MDT 2018
$

About a month from now...

P.S. To make this even more mysterious, I searched in sleep.c and found no
instances of the string "infinity", which makes me wonder how/why this
works at all...

--
A Catholic woman tells her husband to buy Viagra.

A Jewish woman tells her husband to buy Pfizer.

Richard Kettlewell

unread,
Apr 9, 2018, 4:26:24 AM4/9/18
to
gaz...@shell.xmission.com (Kenny McCormack) writes:
> Anyway, back to "GNU sleep", I was curious as to how "infinity" was
> actually implemented and was a bit surprised by what I found.
>
> $ strace sleep infinity
> (lots of stuff, ending with)
> munmap(0x7f0e4f66e000, 81202) = 0
> brk(NULL) = 0x178e000
> brk(0x17af000) = 0x17af000
> nanosleep({2073600, 999999999},
>
> Which leads to the question: What is 2073600???
>
> Observe:
> $ date -d '2073600 seconds'
> Thu May 3 01:17:52 MDT 2018
> $
>
> About a month from now...

http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/nanosleep.c;h=8c3be40221aaca68e719dc89bb0fc037204faa90;hb=HEAD#l50

/* nanosleep mishandles large sleeps due to internal overflow problems.
The worst known case of this is Linux 2.6.9 with glibc 2.3.4, which
can’t sleep more than 24.85 days (2^31 milliseconds). Similarly,
cygwin 1.5.x, which can’t sleep more than 49.7 days (2^32 milliseconds).
Solve this by breaking the sleep up into smaller chunks. */

...and because the worst case is just over 24 days, the chunks are that
long:

const time_t limit = 24 * 24 * 60 * 60;

> P.S. To make this even more mysterious, I searched in sleep.c and
> found no instances of the string "infinity", which makes me wonder
> how/why this works at all...

You need to look deeper than sleep.c. If you happen to start reading
documentation rather than code, skip the man pages (which aren’t all
quite accurate in Linux) and use the info docs instead.

--
https://www.greenend.org.uk/rjk/

Kenny McCormack

unread,
Apr 9, 2018, 9:58:30 AM4/9/18
to
In article <87po38n...@LkoBDZeT.terraraq.uk>,
Richard Kettlewell <inv...@invalid.invalid> wrote:
>gaz...@shell.xmission.com (Kenny McCormack) writes:
>> Anyway, back to "GNU sleep", I was curious as to how "infinity" was
>> actually implemented and was a bit surprised by what I found.
>>
>> $ strace sleep infinity
>> (lots of stuff, ending with)
>> munmap(0x7f0e4f66e000, 81202) = 0
>> brk(NULL) = 0x178e000
>> brk(0x17af000) = 0x17af000
>> nanosleep({2073600, 999999999},
>>
>> Which leads to the question: What is 2073600???
...
> /* nanosleep mishandles large sleeps due to internal overflow problems.
> The worst known case of this is Linux 2.6.9 with glibc 2.3.4, which
> can’t sleep more than 24.85 days (2^31 milliseconds). Similarly,
> cygwin 1.5.x, which can’t sleep more than 49.7 days (2^32 milliseconds).
> Solve this by breaking the sleep up into smaller chunks. */

I see. Which leads to:
1) Why not just use pause(2)? That's what I'd use if I were coding an
infinite sleep.
2) Why not fix the (kernel) bugs?

I had intended to mention pause(2) in the OP, but forgot to do so.

>> P.S. To make this even more mysterious, I searched in sleep.c and
>> found no instances of the string "infinity", which makes me wonder
>> how/why this works at all...
>
>You need to look deeper than sleep.c.

Yeah, I figured it was probably in some other bit of source. Obviously, I
didn't intend on spending too much time digging.

>If you happen to start reading
>documentation rather than code, skip the man pages (which aren't all
>quite accurate in Linux) and use the info docs instead.

I see. Which leads to:
1) I don't do info. I know it is better, but I can't stand the interface.
2) Why not fix the man pages?

Anyway, thanks for responding. Very helpful.

--
The randomly chosen signature file that would have appeared here is more than 4
lines long. As such, it violates one or more Usenet RFCs. In order to remain
in compliance with said RFCs, the actual sig can be found at the following URL:
http://user.xmission.com/~gazelle/Sigs/Rorschach

Richard Kettlewell

unread,
Apr 9, 2018, 10:48:58 AM4/9/18
to
gaz...@shell.xmission.com (Kenny McCormack) writes:
> Richard Kettlewell <inv...@invalid.invalid> wrote:
>>gaz...@shell.xmission.com (Kenny McCormack) writes:
>>> Which leads to the question: What is 2073600???
> ...
>> /* nanosleep mishandles large sleeps due to internal overflow problems.
>> The worst known case of this is Linux 2.6.9 with glibc 2.3.4, which
>> can’t sleep more than 24.85 days (2^31 milliseconds). Similarly,
>> cygwin 1.5.x, which can’t sleep more than 49.7 days (2^32 milliseconds).
>> Solve this by breaking the sleep up into smaller chunks. */
>
> I see. Which leads to:
> 1) Why not just use pause(2)? That's what I'd use if I were coding an
> infinite sleep.

I don’t know what was in the minds of the coreutils authors. But what
you’re suggesting amounts to making the code more complex to support an
out-of-spec edge case, which seems like sufficient explanation if it
even occurred to them to consider it.

> 2) Why not fix the (kernel) bugs?

I expect they have been fixed; 2.6.9 is ancient.

--
https://www.greenend.org.uk/rjk/

Scott Lurndal

unread,
Apr 9, 2018, 11:16:14 AM4/9/18
to
gaz...@shell.xmission.com (Kenny McCormack) writes:

>I see. Which leads to:
> 1) Why not just use pause(2)? That's what I'd use if I were coding an
> infinite sleep.

And if another thread in the process catches a signal, the pause will
awaken.

Richard Kettlewell

unread,
Apr 9, 2018, 11:20:52 AM4/9/18
to
I look forward to the multi-threaded implementation of /bin/sleep l-)

--
https://www.greenend.org.uk/rjk/

Rainer Weikusat

unread,
Apr 9, 2018, 11:21:14 AM4/9/18
to
gaz...@shell.xmission.com (Kenny McCormack) writes:
> In article <87po38n...@LkoBDZeT.terraraq.uk>,
> Richard Kettlewell <inv...@invalid.invalid> wrote:
>>gaz...@shell.xmission.com (Kenny McCormack) writes:
>>> Anyway, back to "GNU sleep", I was curious as to how "infinity" was
>>> actually implemented and was a bit surprised by what I found.
>>>
>>> $ strace sleep infinity
>>> (lots of stuff, ending with)
>>> munmap(0x7f0e4f66e000, 81202) = 0
>>> brk(NULL) = 0x178e000
>>> brk(0x17af000) = 0x17af000
>>> nanosleep({2073600, 999999999},
>>>
>>> Which leads to the question: What is 2073600???
> ...
>> /* nanosleep mishandles large sleeps due to internal overflow problems.
>> The worst known case of this is Linux 2.6.9 with glibc 2.3.4, which
>> can’t sleep more than 24.85 days (2^31 milliseconds). Similarly,
>> cygwin 1.5.x, which can’t sleep more than 49.7 days (2^32 milliseconds).
>> Solve this by breaking the sleep up into smaller chunks. */
>
> I see. Which leads to:
> 1) Why not just use pause(2)? That's what I'd use if I were coding an
> infinite sleep.

Then why not use it?

-----
/* includes */
#include <unistd.h>

/* main */
int main(void)
{
pause();
return 0;
}
----

Kenny McCormack

unread,
Apr 9, 2018, 11:27:33 AM4/9/18
to
In article <87fu44m...@doppelsaurus.mobileactivedefense.com>,
Rainer Weikusat <rwei...@talktalk.net> wrote:
>gaz...@shell.xmission.com (Kenny McCormack) writes:
>> In article <87po38n...@LkoBDZeT.terraraq.uk>,
>> Richard Kettlewell <inv...@invalid.invalid> wrote:
>>>gaz...@shell.xmission.com (Kenny McCormack) writes:
>>>> Anyway, back to "GNU sleep", I was curious as to how "infinity" was
>>>> actually implemented and was a bit surprised by what I found.
>>>>
>>>> $ strace sleep infinity
>>>> (lots of stuff, ending with)
>>>> munmap(0x7f0e4f66e000, 81202) = 0
>>>> brk(NULL) = 0x178e000
>>>> brk(0x17af000) = 0x17af000
>>>> nanosleep({2073600, 999999999},
>>>>
>>>> Which leads to the question: What is 2073600???
>> ...
>>> /* nanosleep mishandles large sleeps due to internal overflow problems.
>>> The worst known case of this is Linux 2.6.9 with glibc 2.3.4, which
>>> can’t sleep more than 24.85 days (2^31 milliseconds). Similarly,
>>> cygwin 1.5.x, which can’t sleep more than 49.7 days (2^32 milliseconds).
>>> Solve this by breaking the sleep up into smaller chunks. */
>>
>> I see. Which leads to:
>> 1) Why not just use pause(2)? That's what I'd use if I were coding an
>> infinite sleep.
>
>Then why not use it?

Indeed.
When I am invited to join the GNU coreutils team, I'll get right on it.
It'll be the first thing I work on.

--
The difference between communism and capitalism?
In capitalism, man exploits man. In communism, it's the other way around.

- Daniel Bell, The End of Ideology (1960) -

Kenny McCormack

unread,
Apr 9, 2018, 11:29:11 AM4/9/18
to
In article <87h8okl...@LkoBDZeT.terraraq.uk>,
Well said, sir.

And note that "infinity" is already a special case (Yes, I know that it
need not be, but for all practical purposes, it is), so it's not a big deal
special-casing its handling.

--
Watching ConservaLoons playing with statistics and facts is like watching a
newborn play with a computer. Endlessly amusing, but totally unproductive.

Rainer Weikusat

unread,
Apr 9, 2018, 11:41:21 AM4/9/18
to
Bit rought but generally functional:

----------
#include <pthread.h>
#include <stdlib.h>
#include <time.h>

struct sleep_data {
time_t until;
int get_up;
};

static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

static void *raiser(void *arg)
{
struct sleep_data *sd;
struct timespec ts;

pthread_mutex_lock(&lock);

sd = arg;
ts.tv_sec = sd->until;
ts.tv_nsec = 0;

do
pthread_cond_timedwait(&cond, &lock, &ts);
while (time(NULL) < sd->until);

sd->get_up = 1;
pthread_cond_signal(&cond);

pthread_mutex_unlock(&lock);

return NULL;
}

static void start_raiser(struct sleep_data *sd)
{
pthread_t tid;

pthread_create(&tid, NULL, raiser, sd);
pthread_detach(tid);
}

int main(int argc, char **argv)
{
struct sleep_data sd;

sd.until = time(NULL) + atoi(argv[1]);
sd.get_up = 0;

pthread_mutex_lock(&lock);

start_raiser(&sd);

do
pthread_cond_wait(&cond, &lock);
while (!sd.get_up);

return 0;
}

Rainer Weikusat

unread,
Apr 9, 2018, 11:47:42 AM4/9/18
to
gaz...@shell.xmission.com (Kenny McCormack) writes:
> In article <87fu44m...@doppelsaurus.mobileactivedefense.com>,
> Rainer Weikusat <rwei...@talktalk.net> wrote:
>>gaz...@shell.xmission.com (Kenny McCormack) writes:
>>> In article <87po38n...@LkoBDZeT.terraraq.uk>,
>>> Richard Kettlewell <inv...@invalid.invalid> wrote:
>>>>gaz...@shell.xmission.com (Kenny McCormack) writes:
>>>>> Anyway, back to "GNU sleep", I was curious as to how "infinity" was
>>>>> actually implemented and was a bit surprised by what I found.
>>>>>
>>>>> $ strace sleep infinity
>>>>> (lots of stuff, ending with)
>>>>> munmap(0x7f0e4f66e000, 81202) = 0
>>>>> brk(NULL) = 0x178e000
>>>>> brk(0x17af000) = 0x17af000
>>>>> nanosleep({2073600, 999999999},
>>>>>
>>>>> Which leads to the question: What is 2073600???
>>> ...
>>>> /* nanosleep mishandles large sleeps due to internal overflow problems.
>>>> The worst known case of this is Linux 2.6.9 with glibc 2.3.4, which
>>>> can’t sleep more than 24.85 days (2^31 milliseconds). Similarly,
>>>> cygwin 1.5.x, which can’t sleep more than 49.7 days (2^32 milliseconds).
>>>> Solve this by breaking the sleep up into smaller chunks. */
>>>
>>> I see. Which leads to:
>>> 1) Why not just use pause(2)? That's what I'd use if I were coding an
>>> infinite sleep.
>>
>>Then why not use it?

[program calling pause]

> Indeed.
> When I am invited to join the GNU coreutils team, I'll get right on it.
> It'll be the first thing I work on.

I'll keep this in mind should I ever feel like starting a "How the evil
GNU project stole my valuable, intellectual property! legal action.

Richard Kettlewell

unread,
Apr 9, 2018, 12:02:50 PM4/9/18
to
gaz...@shell.xmission.com (Kenny McCormack) writes:
> Richard Kettlewell <inv...@invalid.invalid> wrote:
>>sc...@slp53.sl.home (Scott Lurndal) writes:
>>> gaz...@shell.xmission.com (Kenny McCormack) writes:
>>>>I see. Which leads to:
>>>> 1) Why not just use pause(2)? That's what I'd use if I were coding an
>>>> infinite sleep.
>>>
>>> And if another thread in the process catches a signal, the pause will
>>> awaken.
>>
>>I look forward to the multi-threaded implementation of /bin/sleep l-)
>
> Well said, sir.
>
> And note that "infinity" is already a special case (Yes, I know that it
> need not be, but for all practical purposes, it is), so it's not a big deal
> special-casing its handling.

It’s not a special case _in sleep_. Your proposal would change that.

--
https://www.greenend.org.uk/rjk/

Kenny McCormack

unread,
Apr 9, 2018, 12:17:29 PM4/9/18
to
In article <87bmesl...@LkoBDZeT.terraraq.uk>,
We're going to have to agree to disagree on that.

(And I think we're done with this sub-thread...)

--
They say compassion is a virtue, but I don't have the time!

- David Byrne -

Richard Kettlewell

unread,
Apr 9, 2018, 1:33:49 PM4/9/18
to
gaz...@shell.xmission.com (Kenny McCormack) writes:
> Richard Kettlewell <inv...@invalid.invalid> wrote:
>> gaz...@shell.xmission.com (Kenny McCormack) writes:
>>> And note that "infinity" is already a special case (Yes, I know that
>>> it need not be, but for all practical purposes, it is), so it's not
>>> a big deal special-casing its handling.
>>
>>It’s not a special case _in sleep_. Your proposal would change that.
>
> We're going to have to agree to disagree on that.

Well, I’ve read and understood the implementation, and you haven’t...

--
https://www.greenend.org.uk/rjk/

Spiros Bousbouras

unread,
Apr 9, 2018, 11:24:12 PM4/9/18
to
On Mon, 9 Apr 2018 13:58:27 +0000 (UTC)
gaz...@shell.xmission.com (Kenny McCormack) wrote:
> In article <87po38n...@LkoBDZeT.terraraq.uk>,
> Richard Kettlewell <inv...@invalid.invalid> wrote:
> >If you happen to start reading
> >documentation rather than code, skip the man pages (which aren't all
> >quite accurate in Linux) and use the info docs instead.
>
> I see. Which leads to:
> 1) I don't do info. I know it is better, but I can't stand the interface.

less /usr/share/info/coreutils*
works for me.
0 new messages