changeset 13852:299859ce1b75

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.
author Bruno Haible <bruno@clisp.org>
date Fri, 12 Nov 2010 15:17:27 +0100
parents a518692b40d4
children 2f3dbd409322
files ChangeLog lib/nanosleep.c lib/sleep.c
diffstat 3 files changed, 18 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- 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.
--- a/lib/nanosleep.c
+++ b/lib/nanosleep.c
@@ -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;
--- a/lib/sleep.c
+++ b/lib/sleep.c
@@ -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 <bruno@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;