sleep, nanosleep: Work around Linux 2.6.9 nanosleep bug.
authorBruno Haible <bruno@clisp.org>
Fri, 12 Nov 2010 14:17:27 +0000 (15:17 +0100)
committerBruno Haible <bruno@clisp.org>
Fri, 12 Nov 2010 14:17:27 +0000 (15:17 +0100)
* lib/sleep.c (rpl_sleep): Split in chunks no larger than 24 days.
* lib/nanosleep.c (nanosleep): Likewise.

ChangeLog
lib/nanosleep.c
lib/sleep.c

index d9e32a8..077649a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2010-11-12  Bruno Haible  <bruno@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.
+
 2010-11-11  Bruno Haible  <bruno@clisp.org>
 
        fcntl-h: Fix for use of C++ on glibc systems.
index 1a455fb..545452d 100644 (file)
@@ -47,10 +47,11 @@ nanosleep (const struct timespec *requested_delay,
            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 @@ nanosleep (const struct timespec *requested_delay,
 
   {
     /* 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;
index 213e5bd..68d434a 100644 (file)
@@ -1,5 +1,5 @@
 /* Pausing execution of the current thread.
-   Copyright (C) 2007, 20092010 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2009-2010 Free Software Foundation, Inc.
    Written by Bruno Haible <bruno@clisp.org>, 2007.
 
    This program is free software: you can redistribute it and/or modify
@@ -50,13 +50,14 @@ sleep (unsigned int seconds)
 /* 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;