From 8cd9b4cd8a34c49e5a9665fc56bd5ebb32d37f5c Mon Sep 17 00:00:00 2001 From: hniksic Date: Mon, 3 Nov 2003 13:57:04 -0800 Subject: [PATCH] [svn] New function xsleep that resumes sleeps interrupted by signals on systems that support nanosleep. --- ChangeLog | 4 ++++ configure.in | 2 +- src/ChangeLog | 6 ++++++ src/cmpt.c | 20 ------------------- src/config.h.in | 3 +++ src/mswindows.c | 40 +++++++++++++------------------------ src/retr.c | 10 +++++----- src/sysdep.h | 3 --- src/utils.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ src/utils.h | 1 + 10 files changed, 86 insertions(+), 55 deletions(-) diff --git a/ChangeLog b/ChangeLog index 70868653..a49627c1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2003-11-03 Hrvoje Niksic + + * configure.in: Check for nanosleep. + 2003-03-09 Nicolas Schodet * Makefile.in: Fixed bad configure.bat scrdir. diff --git a/configure.in b/configure.in index dd155ec0..eed67f1e 100644 --- a/configure.in +++ b/configure.in @@ -194,7 +194,7 @@ AC_FUNC_MMAP AC_CHECK_FUNCS(strdup strstr strcasecmp strncasecmp strpbrk memmove) AC_CHECK_FUNCS(gettimeofday mktime strptime strerror snprintf vsnprintf) AC_CHECK_FUNCS(select sigblock sigsetjmp signal symlink access isatty) -AC_CHECK_FUNCS(uname gethostname usleep) +AC_CHECK_FUNCS(uname gethostname nanosleep usleep) dnl dnl Check if we need to compile in getopt.c. diff --git a/src/ChangeLog b/src/ChangeLog index 2af36060..e507c588 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2003-11-03 Hrvoje Niksic + + * utils.c (xsleep): New function. Uses nanosleep where available, + resuming sleeps interrupted by signals. Updated callers of sleep + and usleep to use xsleep. + 2003-11-03 Hrvoje Niksic * ftp-basic.c (ftp_login): Remove shadowing (and bogus) diff --git a/src/cmpt.c b/src/cmpt.c index ea1f44ae..9e78b21a 100644 --- a/src/cmpt.c +++ b/src/cmpt.c @@ -1431,26 +1431,6 @@ const unsigned short int __mon_yday[2][13] = }; #endif -#ifndef HAVE_USLEEP -#ifndef WINDOWS - -/* A simple usleep implementation based on select(). For Unix and - Unix-like systems. */ - -int -usleep (unsigned long usec) -{ - struct timeval tm; - tm.tv_sec = 0; - tm.tv_usec = usec; - select (0, NULL, NULL, NULL, &tm); - return 0; -} - -#endif /* not WINDOWS */ -#endif /* not HAVE_USLEEP */ - - /* Currently unused in Wget. Uncomment if we start using memmove again. */ #if 0 diff --git a/src/config.h.in b/src/config.h.in index c4da0f71..2ae45ee8 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -191,6 +191,9 @@ char *alloca (); /* Define if you have the usleep function. */ #undef HAVE_USLEEP +/* Define if you have the nanosleep function. */ +#undef HAVE_NANOSLEEP + /* Define if you have the header file. */ #undef HAVE_STRING_H diff --git a/src/mswindows.c b/src/mswindows.c index 3f36d2c5..36aef00f 100644 --- a/src/mswindows.c +++ b/src/mswindows.c @@ -74,35 +74,23 @@ static DWORD set_sleep_mode (DWORD mode); static DWORD pwr_mode = 0; static int windows_nt_p; -#ifndef HAVE_SLEEP +/* Windows version of xsleep in utils.c. */ -/* Emulation of Unix sleep. */ - -unsigned int -sleep (unsigned seconds) -{ - return SleepEx (1000 * seconds, TRUE) ? 0U : 1000 * seconds; -} -#endif - -#ifndef HAVE_USLEEP -/* Emulation of Unix usleep(). This has a granularity of - milliseconds, but that's ok because: - - a) Wget is only using it with milliseconds [not anymore, but b) - still applies]; - - b) You can't rely on usleep's granularity anyway. If a caller - expects usleep to respect every microsecond, he's in for a - surprise. */ - -int -usleep (unsigned long usec) +void +xsleep (double seconds) { - SleepEx (usec / 1000, TRUE); - return 0; +#ifdef HAVE_USLEEP + if (seconds > 1000) + { + /* Explained in utils.c. */ + sleep (seconds); + seconds -= (long) seconds; + } + usleep (seconds * 1000000L); +#else /* not HAVE_USLEEP */ + SleepEx (seconds * 1000, FALSE); +#endif /* not HAVE_USLEEP */ } -#endif /* HAVE_USLEEP */ void windows_main_junk (int *argc, char **argv, char **exec_name) diff --git a/src/retr.c b/src/retr.c index 637f9316..c3da1641 100644 --- a/src/retr.c +++ b/src/retr.c @@ -114,7 +114,7 @@ limit_bandwidth (long bytes, double *dltime, struct wget_timer *timer) slp, limit_data.chunk_bytes, limit_data.sleep_adjust)); t0 = *dltime; - usleep ((unsigned long) (1000 * slp)); + xsleep (slp / 1000); t1 = wtimer_elapsed (timer); /* Due to scheduling, we probably slept slightly longer (or @@ -642,9 +642,9 @@ sleep_between_retrievals (int count) /* If opt.waitretry is specified and this is a retry, wait for COUNT-1 number of seconds, or for opt.waitretry seconds. */ if (count <= opt.waitretry) - sleep (count - 1); + xsleep (count - 1); else - usleep (1000000L * opt.waitretry); + xsleep (opt.waitretry); } else if (opt.wait) { @@ -652,7 +652,7 @@ sleep_between_retrievals (int count) /* If random-wait is not specified, or if we are sleeping between retries of the same download, sleep the fixed interval. */ - usleep (1000000L * opt.wait); + xsleep (opt.wait); else { /* Sleep a random amount of time averaging in opt.wait @@ -661,7 +661,7 @@ sleep_between_retrievals (int count) double waitsecs = 2 * opt.wait * random_float (); DEBUGP (("sleep_between_retrievals: avg=%f,sleep=%f\n", opt.wait, waitsecs)); - usleep (1000000L * waitsecs); + xsleep (waitsecs); } } } diff --git a/src/sysdep.h b/src/sysdep.h index 96c061b9..2c945795 100644 --- a/src/sysdep.h +++ b/src/sysdep.h @@ -183,9 +183,6 @@ int snprintf (); #ifndef HAVE_VSNPRINTF int vsnprintf (); #endif -#ifndef HAVE_USLEEP -int usleep PARAMS ((unsigned long)); -#endif #ifndef HAVE_MEMMOVE void *memmove (); #endif diff --git a/src/utils.c b/src/utils.c index a427e736..5b577587 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1851,3 +1851,55 @@ run_with_timeout (double timeout, void (*fun) (void *), void *arg) } #endif /* not WINDOWS */ #endif /* not USE_SIGNAL_TIMEOUT */ + +#ifndef WINDOWS + +/* Sleep the specified amount of seconds. On machines without + nanosleep(), this may sleep shorter if interrupted by signals. */ + +void +xsleep (double seconds) +{ +#ifdef HAVE_NANOSLEEP + /* nanosleep is the preferred interface because it offers high + accuracy and, more importantly, because it allows us to reliably + restart after having been interrupted by a signal such as + SIGWINCH. */ + struct timespec sleep, remaining; + sleep.tv_sec = (long) seconds; + sleep.tv_nsec = 1000000000L * (seconds - (long) seconds); + while (nanosleep (&sleep, &remaining) < 0 && errno == EINTR) + /* If nanosleep has been interrupted by a signal, adjust the + sleeping period and return to sleep. */ + sleep = remaining; +#else /* not HAVE_NANOSLEEP */ +#ifdef HAVE_USLEEP + /* If usleep is available, use it in preference to select. */ + if (seconds > 1000) + { + /* usleep apparently accepts unsigned long, which means it can't + sleep longer than ~70 min (35min if signed). If the period + is larger than what usleep can safely handle, use sleep + first, then add usleep for subsecond accuracy. */ + sleep (seconds); + seconds -= (long) seconds; + } + usleep (seconds * 1000000L); +#else /* not HAVE_USLEEP */ +#ifdef HAVE_SELECT + struct timeval sleep; + sleep.tv_sec = (long) seconds; + sleep.tv_usec = 1000000L * (seconds - (long) seconds); + select (0, NULL, NULL, NULL, &sleep); + /* If select returns -1 and errno is EINTR, it means we were + interrupted by a signal. But without knowing how long we've + actually slept, we can't return to sleep. Using gettimeofday to + track sleeps is slow and unreliable due to clock skew. */ +#else /* not HAVE_SELECT */ + sleep (seconds); +#endif /* not HAVE_SELECT */ +#endif /* not HAVE_USLEEP */ +#endif /* not HAVE_NANOSLEEP */ +} + +#endif /* not WINDOWS */ diff --git a/src/utils.h b/src/utils.h index 3e35e333..972d5502 100644 --- a/src/utils.h +++ b/src/utils.h @@ -121,5 +121,6 @@ int random_number PARAMS ((int)); double random_float PARAMS ((void)); int run_with_timeout PARAMS ((double, void (*) (void *), void *)); +void xsleep PARAMS ((double)); #endif /* UTILS_H */ -- 2.39.2