bug-gnulib
[Top][All Lists]
Advanced

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

Re: OpenBSD 4.7 vs nanosleep


From: Bruno Haible
Subject: Re: OpenBSD 4.7 vs nanosleep
Date: Fri, 8 Oct 2010 21:55:09 +0200
User-agent: KMail/1.9.9

Hi Jim,

> This isn't a show-stopper for the coreutils release.

But it's easy to fix. The bug is actually in the gnulib replacement, which
is missing a check on the validity of the argument.


2010-10-08  Bruno Haible  <address@hidden>

        nanosleep: Make replacement POSIX compliant.
        * lib/nanosleep.c (nanosleep): Return -1/EINVAL if the delay's tv_nsec
        is out of range.
        Reported by Jim Meyering.

*** lib/nanosleep.c.orig        Fri Oct  8 21:50:25 2010
--- lib/nanosleep.c     Fri Oct  8 21:49:56 2010
***************
*** 50,87 ****
    /* 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.  Verify that time_t
!      is large enough.  */
!   verify (TYPE_MAXIMUM (time_t) / 49 / 24 / 60 / 60);
!   const time_t limit = 49 * 24 * 60 * 60;
!   time_t seconds = requested_delay->tv_sec;
!   struct timespec intermediate;
!   intermediate.tv_nsec = 0;
  
!   while (limit < seconds)
      {
!       int result;
!       intermediate.tv_sec = limit;
!       result = nanosleep (&intermediate, remaining_delay);
!       seconds -= limit;
!       if (result)
!         {
!           if (remaining_delay)
!             {
!               remaining_delay->tv_sec += seconds;
!               remaining_delay->tv_nsec += requested_delay->tv_nsec;
!               if (BILLION <= requested_delay->tv_nsec)
!                 {
!                   remaining_delay->tv_sec++;
!                   remaining_delay->tv_nsec -= BILLION;
!                 }
!             }
!           return result;
!         }
      }
!   intermediate.tv_sec = seconds;
!   intermediate.tv_nsec = requested_delay->tv_nsec;
!   return nanosleep (&intermediate, remaining_delay);
  }
  
  #elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
--- 50,96 ----
    /* 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.  */
  
!   if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)
      {
!       errno = EINVAL;
!       return -1;
      }
! 
!   {
!     /* Verify that time_t is large enough.  */
!     verify (TYPE_MAXIMUM (time_t) / 49 / 24 / 60 / 60);
!     const time_t limit = 49 * 24 * 60 * 60;
!     time_t seconds = requested_delay->tv_sec;
!     struct timespec intermediate;
!     intermediate.tv_nsec = 0;
! 
!     while (limit < seconds)
!       {
!         int result;
!         intermediate.tv_sec = limit;
!         result = nanosleep (&intermediate, remaining_delay);
!         seconds -= limit;
!         if (result)
!           {
!             if (remaining_delay)
!               {
!                 remaining_delay->tv_sec += seconds;
!                 remaining_delay->tv_nsec += requested_delay->tv_nsec;
!                 if (BILLION <= requested_delay->tv_nsec)
!                   {
!                     remaining_delay->tv_sec++;
!                     remaining_delay->tv_nsec -= BILLION;
!                   }
!               }
!             return result;
!           }
!       }
!     intermediate.tv_sec = seconds;
!     intermediate.tv_nsec = requested_delay->tv_nsec;
!     return nanosleep (&intermediate, remaining_delay);
!   }
  }
  
  #elif (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__



reply via email to

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