# HG changeset patch # User Bruno Haible # Date 1286567576 -7200 # Node ID 3a4a1b81c846112142a21bbccc7d0afbeab57cd3 # Parent e9b975e48d337d67b24570622d39f278826fd13c 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. diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2010-10-08 Bruno Haible + + 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. + 2010-10-08 Paul Eggert bootstrap: add hook for altering gnulib.mk, for Bison diff --git a/lib/nanosleep.c b/lib/nanosleep.c --- a/lib/nanosleep.c +++ b/lib/nanosleep.c @@ -50,38 +50,47 @@ /* 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; + by breaking the sleep up into smaller chunks. */ - while (limit < seconds) + if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec) { - 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; - } + errno = EINVAL; + return -1; } - intermediate.tv_sec = seconds; - intermediate.tv_nsec = requested_delay->tv_nsec; - return nanosleep (&intermediate, remaining_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; + 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__