Mercurial > hg > octave-lyh > gnulib-hg
changeset 7237:119870bc83d7
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>.
* 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.
author | Paul Eggert <eggert@cs.ucla.edu> |
---|---|
date | Thu, 31 Aug 2006 07:00:50 +0000 |
parents | c05b41ab8e3b |
children | e3f65c753bef |
files | ChangeLog lib/ChangeLog lib/nanosleep.c m4/ChangeLog m4/nanosleep.m4 modules/gettime |
diffstat | 6 files changed, 158 insertions(+), 34 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +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>
--- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,13 @@ +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
--- a/lib/nanosleep.c +++ b/lib/nanosleep.c @@ -52,16 +52,74 @@ #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; @@ -107,7 +165,7 @@ /* set up sig handler */ if (! initialized) { -#ifdef SA_NOCLDSTOP +# ifdef SA_NOCLDSTOP struct sigaction oldact, newact; newact.sa_handler = sighandler; sigemptyset (&newact.sa_mask); @@ -116,13 +174,13 @@ 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; } @@ -143,3 +201,4 @@ return suspended; } +#endif
--- a/m4/ChangeLog +++ b/m4/ChangeLog @@ -1,3 +1,13 @@ +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.
--- a/m4/nanosleep.m4 +++ b/m4/nanosleep.m4 @@ -1,4 +1,4 @@ -#serial 18 +#serial 19 dnl From Jim Meyering. dnl Check for the nanosleep function. @@ -18,6 +18,7 @@ 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 @@ -27,42 +28,81 @@ 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 ])