nanosleep mishandles sleeps for longer than 2**31 seconds.
Problem reported by Frank v Waveren in
<http://lists.gnu.org/archive/html/bug-coreutils/2006-08/msg00298.html>.
* lib/nanosleep.c (BILLION): New constant.
(getnow) [HAVE_BUG_BIG_NANOSLEEP]: New functions.
(rpl_nanosleep) [HAVE_BUG_BIG_NANOSLEEP]: Completely new implementation.
* m4/nanosleep.m4 (gl_FUNC_NANOSLEEP): Require gl_CLOCK_TIME.
* modules/nanosleep (Depends-on): Add gettime.
+2006-08-30 Paul Eggert <eggert@cs.ucla.edu>
+
+ * modules/nanosleep (Depends-on): Add gettime.
+
2006-08-30 Paul Eggert <eggert@cs.ucla.edu>
and Simon Josefsson <jas@extundo.com>
and Oskar Liljeblad <oskar@osk.mine.nu>
+2006-08-30 Paul Eggert <eggert@cs.ucla.edu>
+
+ Work around a bug in both the Linux and SunOS 64-bit kernels:
+ nanosleep mishandles sleeps for longer than 2**31 seconds.
+ Problem reported by Frank v Waveren in
+ <http://lists.gnu.org/archive/html/bug-coreutils/2006-08/msg00298.html>.
+ * nanosleep.c (BILLION): New constant.
+ (getnow) [HAVE_BUG_BIG_NANOSLEEP]: New functions.
+ (rpl_nanosleep) [HAVE_BUG_BIG_NANOSLEEP]: Completely new implementation.
+
2006-08-30 Jim Meyering <jim@meyering.net>
* isapipe.c (isapipe): Rename local s/fd/fd_pair/ to avoid shadowing
#include "timespec.h"
+enum { BILLION = 1000 * 1000 * 1000 };
+
+#if HAVE_BUG_BIG_NANOSLEEP
+
+void
+getnow (struct timespec *t)
+{
+# if defined CLOCK_MONOTONIC && HAVE_CLOCK_GETTIME
+ if (clock_gettime (CLOCK_MONOTONIC, t) == 0)
+ return;
+# endif
+ gettime (t);
+}
+
+int
+rpl_nanosleep (const struct timespec *requested_delay,
+ struct timespec *remaining_delay)
+{
+ /* nanosleep mishandles large sleeps due to internal overflow
+ problems, so check that the proper amount of time has actually
+ elapsed. */
+
+ struct timespec delay = *requested_delay;
+ struct timespec t0;
+ getnow (&t0);
+
+ for (;;)
+ {
+ int r = nanosleep (&delay, remaining_delay);
+ if (r == 0)
+ {
+ time_t secs_sofar;
+ struct timespec now;
+ getnow (&now);
+
+ secs_sofar = now.tv_sec - t0.tv_sec;
+ if (requested_delay->tv_sec < secs_sofar)
+ return 0;
+ delay.tv_sec = requested_delay->tv_sec - secs_sofar;
+ delay.tv_nsec = requested_delay->tv_nsec - (now.tv_nsec - t0.tv_nsec);
+ if (delay.tv_nsec < 0)
+ {
+ if (delay.tv_sec == 0)
+ return 0;
+ delay.tv_nsec += BILLION;
+ delay.tv_sec--;
+ }
+ else if (BILLION <= delay.tv_nsec)
+ {
+ delay.tv_nsec -= BILLION;
+ delay.tv_sec++;
+ }
+ }
+ }
+}
+
+#else
+
/* Some systems (MSDOS) don't have SIGCONT.
Using SIGTERM here turns the signal-handling code below
into a no-op on such systems. */
-#ifndef SIGCONT
-# define SIGCONT SIGTERM
-#endif
+# ifndef SIGCONT
+# define SIGCONT SIGTERM
+# endif
-#if ! HAVE_SIGINTERRUPT
-# define siginterrupt(sig, flag) /* empty */
-#endif
+# if ! HAVE_SIGINTERRUPT
+# define siginterrupt(sig, flag) /* empty */
+# endif
static sig_atomic_t volatile suspended;
/* set up sig handler */
if (! initialized)
{
-#ifdef SA_NOCLDSTOP
+# ifdef SA_NOCLDSTOP
struct sigaction oldact, newact;
newact.sa_handler = sighandler;
sigemptyset (&newact.sa_mask);
sigaction (SIGCONT, NULL, &oldact);
if (oldact.sa_handler != SIG_IGN)
sigaction (SIGCONT, &newact, NULL);
-#else
+# else
if (signal (SIGCONT, SIG_IGN) != SIG_IGN)
{
signal (SIGCONT, sighandler);
siginterrupt (SIGCONT, 1);
}
-#endif
+# endif
initialized = true;
}
return suspended;
}
+#endif
+2006-08-30 Paul Eggert <eggert@cs.ucla.edu>
+
+ Work around a bug in both the Linux and SunOS 64-bit kernels:
+ nanosleep mishandles sleeps for longer than 2**31 seconds.
+ Problem reported by Frank v Waveren in
+ <http://lists.gnu.org/archive/html/bug-coreutils/2006-08/msg00298.html>.
+ * nanosleep.m4 (gl_FUNC_NANOSLEEP): Require gl_CLOCK_TIME.
+ Check for nanosleep bug.
+ (LIB_NANOSLEEP): Append clock_gettime library if needed.
+
2006-08-29 Paul Eggert <eggert@cs.ucla.edu>
* isapipe.m4: New file.
-#serial 18
+#serial 19
dnl From Jim Meyering.
dnl Check for the nanosleep function.
AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
AC_REQUIRE([AC_HEADER_TIME])
+ AC_REQUIRE([gl_CLOCK_TIME])
AC_CHECK_HEADERS_ONCE(sys/time.h)
nanosleep_save_libs=$LIBS
AC_SEARCH_LIBS([nanosleep], [rt posix4],
[test "$ac_cv_search_nanosleep" = "none required" ||
LIB_NANOSLEEP=$ac_cv_search_nanosleep])
- AC_SUBST([LIB_NANOSLEEP])
- AC_CACHE_CHECK([for nanosleep],
+ AC_CACHE_CHECK([for working nanosleep],
[gl_cv_func_nanosleep],
[
- AC_LINK_IFELSE([AC_LANG_SOURCE([[
-# if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-# else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-# endif
+ AC_RUN_IFELSE(
+ [AC_LANG_SOURCE([[
+ #if TIME_WITH_SYS_TIME
+ #include <sys/time.h>
+ #include <time.h>
+ #else
+ #if HAVE_SYS_TIME_H
+ #include <sys/time.h>
+ #else
+ #include <time.h>
+ #endif
+ #endif
+ #include <errno.h>
+ #include <limits.h>
+ #include <signal.h>
+ #include <unistd.h>
+ #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+ #define TYPE_MAXIMUM(t) \
+ ((t) (! TYPE_SIGNED (t) \
+ ? (t) -1 \
+ : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))))
+
+ static void
+ check_for_SIGALRM (int sig)
+ {
+ if (sig != SIGALRM)
+ _exit (1);
+ }
- int
- main ()
- {
- struct timespec ts_sleep, ts_remaining;
- ts_sleep.tv_sec = 0;
- ts_sleep.tv_nsec = 1;
- return nanosleep (&ts_sleep, &ts_remaining) < 0;
- }
- ]])],
+ int
+ main ()
+ {
+ static struct timespec ts_sleep;
+ static struct timespec ts_remaining;
+ static struct sigaction act;
+ act.sa_handler = check_for_SIGALRM;
+ sigemptyset (&act.sa_mask);
+ sigaction (SIGALRM, &act, NULL);
+ ts_sleep.tv_sec = TYPE_MAXIMUM (time_t);
+ ts_sleep.tv_nsec = 999999999;
+ alarm (1);
+ if (nanosleep (&ts_sleep, &ts_remaining) == -1 && errno == EINTR
+ && TYPE_MAXIMUM (time_t) - 10 < ts_remaining.tv_sec)
+ return 0;
+ return 119;
+ }]])],
[gl_cv_func_nanosleep=yes],
- [gl_cv_func_nanosleep=no])
+ [case $? in dnl (
+ 119) gl_cv_func_nanosleep='no (mishandles large arguments)';; dnl (
+ *) gl_cv_func_nanosleep=no;;
+ esac],
+ [gl_cv_func_nanosleep=cross-compiling])
])
- if test $gl_cv_func_nanosleep = no; then
+ if test "$gl_cv_func_nanosleep" != yes; then
+ if test "$gl_cv_func_nanosleep" = 'no (mishandles large arguments)'; then
+ AC_DEFINE([HAVE_BUG_BIG_NANOSLEEP], 1,
+ [Define to 1 if nanosleep mishandle large arguments.])
+ for ac_lib in $LIB_CLOCK_GETTIME; do
+ case " $LIB_NANOSLEEP " in
+ *" $ac_lib "*) ;;
+ *) LIB_NANOSLEEP="$LIB_NANOSLEEP $ac_lib";;
+ esac
+ done
+ fi
AC_LIBOBJ(nanosleep)
AC_DEFINE(nanosleep, rpl_nanosleep,
[Define to rpl_nanosleep if the replacement function should be used.])
gl_PREREQ_NANOSLEEP
fi
+ AC_SUBST([LIB_NANOSLEEP])
LIBS=$nanosleep_save_libs
])
m4/gettime.m4
Depends-on:
+gettime
gettimeofday
timespec
extensions