on systems that support nanosleep.
+2003-11-03 Hrvoje Niksic <hniksic@xemacs.org>
+
+ * configure.in: Check for nanosleep.
+
2003-03-09 Nicolas Schodet <contact@ni.fr.eu.org>
* Makefile.in: Fixed bad configure.bat scrdir.
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.
+2003-11-03 Hrvoje Niksic <hniksic@xemacs.org>
+
+ * 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 <hniksic@xemacs.org>
* ftp-basic.c (ftp_login): Remove shadowing (and bogus)
};
#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
/* 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 <string.h> header file. */
#undef HAVE_STRING_H
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)
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
/* 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)
{
/* 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
double waitsecs = 2 * opt.wait * random_float ();
DEBUGP (("sleep_between_retrievals: avg=%f,sleep=%f\n",
opt.wait, waitsecs));
- usleep (1000000L * waitsecs);
+ xsleep (waitsecs);
}
}
}
#ifndef HAVE_VSNPRINTF
int vsnprintf ();
#endif
-#ifndef HAVE_USLEEP
-int usleep PARAMS ((unsigned long));
-#endif
#ifndef HAVE_MEMMOVE
void *memmove ();
#endif
}
#endif /* not WINDOWS */
#endif /* not USE_SIGNAL_TIMEOUT */
+\f
+#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 */
double random_float PARAMS ((void));
int run_with_timeout PARAMS ((double, void (*) (void *), void *));
+void xsleep PARAMS ((double));
#endif /* UTILS_H */