bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

sleep, nanosleep test failures


From: Bruno Haible
Subject: sleep, nanosleep test failures
Date: Fri, 12 Nov 2010 11:57:39 +0100
User-agent: KMail/1.9.9

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  <address@hidden>

        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 <address@hidden>, 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;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]