]> sjero.net Git - wget/commitdiff
[svn] Subsecond granularity in run_with_timeout.
authorhniksic <devnull@localhost>
Thu, 2 Oct 2003 13:37:45 +0000 (06:37 -0700)
committerhniksic <devnull@localhost>
Thu, 2 Oct 2003 13:37:45 +0000 (06:37 -0700)
NEWS
src/ChangeLog
src/utils.c

diff --git a/NEWS b/NEWS
index 7dbb710a70b85145551e04b964af60910e466577..ed0206db6e79e73baef4b4c1bddbd7f47fa220f7 100644 (file)
--- 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'.
 \f
 * Wget 1.8.2 is a bugfix release with no user-visible changes.
 \f
index 84aaebdda52508eb79befac3cdb3ea4e929d4b92..9f403b6b6acd5ac25de827acbee6dcc1f93c85a6 100644 (file)
@@ -1,3 +1,11 @@
+2003-10-02  Hrvoje Niksic  <hniksic@xemacs.org>
+
+       * 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  <hniksic@xemacs.org>
 
        * url.c (url_parse): Don't leak memory when a reencoded URL turns
index 85274e9902ebbe85e20600f472c09dd7ab6df6af..9586a8b7c6f9a512e7526bec8dd9ce4d7afcf4bc 100644 (file)
@@ -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;