From 030704403b55a5be2c58d41f9511fc1f03a6979e Mon Sep 17 00:00:00 2001 From: hniksic Date: Thu, 2 Oct 2003 06:37:45 -0700 Subject: [PATCH] [svn] Subsecond granularity in run_with_timeout. --- NEWS | 10 ++++----- src/ChangeLog | 8 +++++++ src/utils.c | 61 +++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 65 insertions(+), 14 deletions(-) diff --git a/NEWS b/NEWS index 7dbb710a..ed0206db 100644 --- a/NEWS +++ b/NEWS @@ -13,8 +13,8 @@ send a POST request with the specified contents. ** IPv6 is experimentally supported. -** The `--timeout' option now affects DNS lookup and establishing the -connection as well. Previously it only affected reading and writing +** The `--timeout' option now also affects DNS lookup and establishing +the TCP connection. Previously it only affected reading and writing data. Those three timeouts can be set separately using `--dns-timeout', `--connection-timeout', and `--read-timeout', respectively. @@ -53,9 +53,9 @@ as "//img.foo.com/foo.jpg". ** Boolean options in `.wgetrc' and on the command line now accept values "yes" and "no" along with the traditional "on" and "off". -** It is now possible to specify decimal values for --timeout, --wait, ---waitretry, and --limit-rate. For instance, `--wait=0.5' now -works as expected, and so does --limit-rate=2.5k. +** It is now possible to specify decimal values for timeouts, waiting +periods, and download rate. For instance, `--wait=0.5' now works as +expected, as does `--dns-timeout=0.5' and even `--limit-rate=2.5k'. * Wget 1.8.2 is a bugfix release with no user-visible changes. diff --git a/src/ChangeLog b/src/ChangeLog index 84aaebdd..9f403b6b 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +2003-10-02 Hrvoje Niksic + + * utils.c (alarm_set): New function; use either setitimer or alarm + to set up the alarm. + (alarm_cancel): New function; cancel the alarm set up by + alarm_set. + (run_with_timeout): Use them. + 2003-10-01 Hrvoje Niksic * url.c (url_parse): Don't leak memory when a reencoded URL turns diff --git a/src/utils.c b/src/utils.c index 85274e99..9586a8b7 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1963,6 +1963,56 @@ abort_run_with_timeout (int sig) longjmp (run_with_timeout_env, -1); } # endif /* not HAVE_SIGSETJMP */ + +/* Arrange for SIGALRM to be delivered in TIMEOUT seconds. This uses + setitimer where available, alarm otherwise. + + TIMEOUT should be non-zero. If the timeout value is so small that + it would be rounded to zero, it is rounded to the least legal value + instead (1us for setitimer, 1s for alarm). That ensures that + SIGALRM will be delivered in all cases. */ + +static void +alarm_set (double timeout) +{ +#ifdef ITIMER_REAL + /* Use the modern itimer interface. */ + struct itimerval itv; + memset (&itv, 0, sizeof (itv)); + itv.it_value.tv_sec = (long) timeout; + itv.it_value.tv_usec = 1000000L * (timeout - (long)timeout); + if (itv.it_value.tv_sec == 0 && itv.it_value.tv_usec == 0) + /* Ensure that we wait for at least the minimum interval. + Specifying zero would mean "wait forever". */ + itv.it_value.tv_usec = 1; + setitimer (ITIMER_REAL, &itv, NULL); +#else /* not ITIMER_REAL */ + /* Use the old alarm() interface. */ + int secs = (int) timeout; + if (secs == 0) + /* Round TIMEOUTs smaller than 1 to 1, not to zero. This is + because alarm(0) means "never deliver the alarm", i.e. "wait + forever", which is not what someone who specifies a 0.5s + timeout would expect. */ + secs = 1; + alarm (secs); +#endif /* not ITIMER_REAL */ +} + +/* Cancel the alarm set with alarm_set. */ + +static void +alarm_cancel (void) +{ +#ifdef ITIMER_REAL + struct itimerval disable; + memset (&disable, 0, sizeof (disable)); + setitimer (ITIMER_REAL, &disable, NULL); +#else /* not ITIMER_REAL */ + alarm (0); +#endif /* not ITIMER_REAL */ +} + #endif /* USE_SIGNAL_TIMEOUT */ int @@ -1980,13 +2030,6 @@ run_with_timeout (double timeout, void (*fun) (void *), void *arg) return 0; } - /* Calling alarm() rounds TIMEOUT. If it is smaller than 1, round - it to 1, not to 0, because alarm(0) means "never deliver the - alarm", i.e. "wait forever", which is not what someone who - specifies a 0.5s timeout would expect. */ - if (timeout < 1) - timeout = 1; - signal (SIGALRM, abort_run_with_timeout); if (SETJMP (run_with_timeout_env) != 0) { @@ -1994,12 +2037,12 @@ run_with_timeout (double timeout, void (*fun) (void *), void *arg) signal (SIGALRM, SIG_DFL); return 1; } - alarm ((int) timeout); + alarm_set (timeout); fun (arg); /* Preserve errno in case alarm() or signal() modifies it. */ saved_errno = errno; - alarm (0); + alarm_cancel (); signal (SIGALRM, SIG_DFL); errno = saved_errno; -- 2.39.2