Hi, On a stock Linux/x86 machine I observe these test failures:
test-nanosleep.c:78: assertion failed FAIL: test-nanosleep test-sleep.c:53: assertion failed FAIL: test-sleep It's a "Red Hat Enterprise Linux ES release 4 (Nahant Update 8)" machine with Linux 2.6.9 kernel and glibc 2.3.4. The reason is that when sleep() is asked to sleep for 49 days and interrupted after 1 second, it returns an "unslept amount" of 24.85 days. This is similar to the Cygwin 1.5.x behaviour, for which we already have a workaround. ltrace execution: signal(14, 0x8048740) = NULL alarm(1) = 0 sleep(4233600 <unfinished ...> --- SIGALRM (Alarm clock) --- <... sleep resumed> ) = 2147156 strace execution: rt_sigaction(SIGALRM, {0x8048740, [ALRM], SA_RESTORER|SA_RESTART, 0x5ee9b8}, {SIG_DFL}, 8) = 0 alarm(1) = 0 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0 rt_sigaction(SIGCHLD, NULL, {SIG_DFL}, 8) = 0 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 nanosleep({4233600, 0}, 0xbfe8a254) = ? ERESTART_RESTARTBLOCK (To be restarted) --- SIGALRM (Alarm clock) @ 0 (0) --- sigreturn() = ? (mask now []) Looking at the implementation of sleep() in glibc, the bug must be really in the kernel. Jim, is this OK to commit? It fixes the issue. 2010-11-12 Bruno Haible <br...@clisp.org> sleep, nanosleep: Work around Linux 2.6.9 nanosleep bug. * lib/sleep.c (rpl_sleep): Split in chunks no larger than 24 days. * lib/nanosleep.c (nanosleep): Likewise. --- lib/sleep.c.orig Fri Nov 12 11:45:59 2010 +++ lib/sleep.c Fri Nov 12 11:34:07 2010 @@ -1,5 +1,5 @@ /* Pausing execution of the current thread. - Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2007, 2009-2010 Free Software Foundation, Inc. Written by Bruno Haible <br...@clisp.org>, 2007. This program is free software: you can redistribute it and/or modify @@ -50,13 +50,14 @@ /* Guarantee unlimited sleep and a reasonable return value. Cygwin 1.5.x rejects attempts to sleep more than 49.7 days (2**32 milliseconds), but uses uninitialized memory which results in a - garbage answer. */ + garbage answer. Similarly, Linux 2.6.9 with glibc 2.3.4 has a too + small return value when asked to sleep more than 24.85 days. */ unsigned int rpl_sleep (unsigned int seconds) { /* This requires int larger than 16 bits. */ - verify (UINT_MAX / 49 / 24 / 60 / 60); - const unsigned int limit = 49 * 24 * 60 * 60; + verify (UINT_MAX / 24 / 24 / 60 / 60); + const unsigned int limit = 24 * 24 * 60 * 60; while (limit < seconds) { unsigned int result; --- lib/nanosleep.c.orig Fri Nov 12 11:45:59 2010 +++ lib/nanosleep.c Fri Nov 12 11:36:49 2010 @@ -47,10 +47,11 @@ struct timespec *remaining_delay) #undef nanosleep { - /* nanosleep mishandles large sleeps due to internal overflow - problems. The worst known case of this is 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. */ + /* 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. */ if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec) { @@ -60,8 +61,8 @@ { /* Verify that time_t is large enough. */ - verify (TYPE_MAXIMUM (time_t) / 49 / 24 / 60 / 60); - const time_t limit = 49 * 24 * 60 * 60; + verify (TYPE_MAXIMUM (time_t) / 24 / 24 / 60 / 60); + const time_t limit = 24 * 24 * 60 * 60; time_t seconds = requested_delay->tv_sec; struct timespec intermediate; intermediate.tv_nsec = 0;