]> sjero.net Git - wget/commitdiff
[svn] Generalize connect_with_timeout into run_with_timeout.
authorhniksic <devnull@localhost>
Sat, 13 Apr 2002 22:18:28 +0000 (15:18 -0700)
committerhniksic <devnull@localhost>
Sat, 13 Apr 2002 22:18:28 +0000 (15:18 -0700)
Published in <sxs4rifxndi.fsf@florida.arsdigita.de>.

src/ChangeLog
src/connect.c
src/host.c
src/utils.c
src/utils.h

index 12912cf68b8cca243cb90f90021b726b15478a9d..e7470ac0c1ce4d963f77afc9b0d2848a5c6eb94c 100644 (file)
@@ -1,3 +1,14 @@
+2002-04-14  Hrvoje Niksic  <hniksic@arsdigita.com>
+
+       * connect.c (connect_with_timeout): Firing SIGALRM can result in
+       connect() exiting with EINTR.  Treat EINTR the same as ETIMEDOUT.
+
+2002-04-13  Hrvoje Niksic  <hniksic@arsdigita.com>
+
+       * connect.c (connect_with_timeout): Use it.
+
+       * utils.c (run_with_timeout): New function.
+
 2002-04-13  Hrvoje Niksic  <hniksic@arsdigita.com>
 
        * url.c (getproxy): Accept a struct url argument.  This obviates
 2002-04-13  Hrvoje Niksic  <hniksic@arsdigita.com>
 
        * url.c (getproxy): Accept a struct url argument.  This obviates
index d95ad74f44c72f3efe1d91343b7af0c7876934fe..29a8b6e0f09c12c3270fac8de09b96fe4aa21eb3 100644 (file)
@@ -47,29 +47,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 # include <sys/select.h>
 #endif /* HAVE_SYS_SELECT_H */
 
 # include <sys/select.h>
 #endif /* HAVE_SYS_SELECT_H */
 
-/* To implement connect with timeout, we need signal and either
-   sigsetjmp or sigblock. */
-#undef UNIX_CONNECT_TIMEOUT
-#ifdef HAVE_SIGNAL_H
-# include <signal.h>
-#endif
-#ifdef HAVE_SETJMP_H
-# include <setjmp.h>
-#endif
-/* If sigsetjmp is a macro, configure won't pick it up. */
-#ifdef sigsetjmp
-# define HAVE_SIGSETJMP
-#endif
-#ifdef HAVE_SIGNAL
-# ifdef HAVE_SIGSETJMP
-#  define UNIX_CONNECT_TIMEOUT
-# endif
-# ifdef HAVE_SIGBLOCK
-#  define UNIX_CONNECT_TIMEOUT
-# endif
-#endif
-
 #include "wget.h"
 #include "wget.h"
+#include "utils.h"
 #include "host.h"
 #include "connect.h"
 
 #include "host.h"
 #include "connect.h"
 
@@ -107,45 +86,19 @@ resolve_bind_address (void)
   bind_address_resolved = 1;
 }
 \f
   bind_address_resolved = 1;
 }
 \f
-#ifndef UNIX_CONNECT_TIMEOUT
-static int
-connect_with_timeout (int fd, const struct sockaddr *addr, int addrlen,
-                     int timeout)
-{
-  return connect (fd, addr, addrlen);
-}
-#else  /* UNIX_CONNECT_TIMEOUT */
-/* Implementation of connect with timeout. */
-
-#ifdef HAVE_SIGSETJMP
-#define SETJMP(env) sigsetjmp (env, 1)
+struct cwt_context {
+  int fd;
+  const struct sockaddr *addr;
+  int addrlen;
+  int result;
+};
 
 
-static sigjmp_buf abort_connect_env;
-
-RETSIGTYPE
-abort_connect (int ignored)
-{
-  siglongjmp (abort_connect_env, -1);
-}
-#else  /* not HAVE_SIGSETJMP */
-#define SETJMP(env) setjmp (env)
-
-static jmp_buf abort_connect_env;
-
-RETSIGTYPE
-abort_connect (int ignored)
+static void
+connect_with_timeout_callback (void *arg)
 {
 {
-  /* We don't have siglongjmp to preserve the set of blocked signals;
-     if we longjumped out of the handler at this point, SIGALRM would
-     remain blocked.  We must unblock it manually. */
-  int mask = siggetmask ();
-  mask &= ~sigmask(SIGALRM);
-  sigsetmask (mask);
-
-  /* Now it's safe to longjump. */
-  longjmp (abort_connect_env, -1);
+  struct cwt_context *ctx = (struct cwt_context *)arg;
+  ctx->result = connect (ctx->fd, ctx->addr, ctx->addrlen);
 }
 }
-#endif /* not HAVE_SIGSETJMP */
 
 /* Like connect, but specifies a timeout.  If connecting takes longer
    than TIMEOUT seconds, -1 is returned and errno is set to
 
 /* Like connect, but specifies a timeout.  If connecting takes longer
    than TIMEOUT seconds, -1 is returned and errno is set to
@@ -155,32 +108,20 @@ static int
 connect_with_timeout (int fd, const struct sockaddr *addr, int addrlen,
                      int timeout)
 {
 connect_with_timeout (int fd, const struct sockaddr *addr, int addrlen,
                      int timeout)
 {
-  int result, saved_errno;
-
-  if (timeout == 0)
-    return connect (fd, addr, addrlen);
+  struct cwt_context ctx;
+  ctx.fd = fd;
+  ctx.addr = addr;
+  ctx.addrlen = addrlen;
 
 
-  signal (SIGALRM, abort_connect);
-  if (SETJMP (abort_connect_env) != 0)
+  if (run_with_timeout (timeout, connect_with_timeout_callback, &ctx))
     {
     {
-      /* Longjumped out of connect with a timeout. */
-      signal (SIGALRM, SIG_DFL);
       errno = ETIMEDOUT;
       return -1;
     }
       errno = ETIMEDOUT;
       return -1;
     }
-
-  alarm (timeout);
-  result = connect (fd, addr, addrlen);
-
-  saved_errno = errno;         /* In case alarm() or signal() change
-                                  errno. */
-  alarm (0);
-  signal (SIGALRM, SIG_DFL);
-  errno = saved_errno;
-
-  return result;
+  if (ctx.result == -1 && errno == EINTR)
+    errno = ETIMEDOUT;
+  return ctx.result;
 }
 }
-#endif /* UNIX_CONNECT_TIMEOUT */
 \f
 /* A kludge, but still better than passing the host name all the way
    to connect_to_one.  */
 \f
 /* A kludge, but still better than passing the host name all the way
    to connect_to_one.  */
index dbe11edb76885ff2ce180843d89172c8c492acb3..45455bf023559e1ecf038840d74fd402d37901bb 100644 (file)
@@ -551,6 +551,10 @@ lookup_host (const char *host, int silent)
   if (!silent)
     logprintf (LOG_VERBOSE, _("Resolving %s... "), host);
 
   if (!silent)
     logprintf (LOG_VERBOSE, _("Resolving %s... "), host);
 
+  /* Host name lookup goes on below.  #### We should implement
+     getaddrinfo_with_timeout and gethostbyname_with_timeout the same
+     way connect.c implements connect_with_timeout.  */
+
 #ifdef INET6
   {
     struct addrinfo hints, *ai;
 #ifdef INET6
   {
     struct addrinfo hints, *ai;
index ca8505acf0c7d9846dd8ae0e83618fc7db0b7a5e..cd1e645d42e7968ec4eb5d8dfdf5d9400b818e5a 100644 (file)
@@ -59,6 +59,27 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 # include <termios.h>
 #endif
 
 # include <termios.h>
 #endif
 
+/* Needed for run_with_timeout. */
+#undef USE_SIGNAL_TIMEOUT
+#ifdef HAVE_SIGNAL_H
+# include <signal.h>
+#endif
+#ifdef HAVE_SETJMP_H
+# include <setjmp.h>
+#endif
+/* If sigsetjmp is a macro, configure won't pick it up. */
+#ifdef sigsetjmp
+# define HAVE_SIGSETJMP
+#endif
+#ifdef HAVE_SIGNAL
+# ifdef HAVE_SIGSETJMP
+#  define USE_SIGNAL_TIMEOUT
+# endif
+# ifdef HAVE_SIGBLOCK
+#  define USE_SIGNAL_TIMEOUT
+# endif
+#endif
+
 #include "wget.h"
 #include "utils.h"
 #include "fnmatch.h"
 #include "wget.h"
 #include "utils.h"
 #include "fnmatch.h"
@@ -1757,3 +1778,73 @@ debug_test_md5 (char *buf)
   return res;
 }
 #endif
   return res;
 }
 #endif
+\f
+/* Implementation of run_with_timeout, a generic timeout handler for
+   systems with Unix-like signal handling.  */
+#ifdef HAVE_SIGSETJMP
+#define SETJMP(env) sigsetjmp (env, 1)
+
+static sigjmp_buf run_with_timeout_env;
+
+static RETSIGTYPE
+abort_run_with_timeout (int sig)
+{
+  assert (sig == SIGALRM);
+  siglongjmp (run_with_timeout_env, -1);
+}
+#else  /* not HAVE_SIGSETJMP */
+#define SETJMP(env) setjmp (env)
+
+static jmp_buf run_with_timeout_env;
+
+static RETSIGTYPE
+abort_run_with_timeout (int sig)
+{
+  assert (sig == SIGALRM);
+  /* We don't have siglongjmp to preserve the set of blocked signals;
+     if we longjumped out of the handler at this point, SIGALRM would
+     remain blocked.  We must unblock it manually. */
+  int mask = siggetmask ();
+  mask &= ~sigmask(SIGALRM);
+  sigsetmask (mask);
+
+  /* Now it's safe to longjump. */
+  longjmp (run_with_timeout_env, -1);
+}
+#endif /* not HAVE_SIGSETJMP */
+
+int
+run_with_timeout (long timeout, void (*fun) (void *), void *arg)
+{
+#ifndef USE_SIGNAL_TIMEOUT
+  fun (arg);
+  return 0;
+#else
+  int saved_errno;
+
+  if (timeout == 0)
+    {
+      fun (arg);
+      return 0;
+    }
+
+  signal (SIGALRM, abort_run_with_timeout);
+  if (SETJMP (run_with_timeout_env) != 0)
+    {
+      /* Longjumped out of FUN with a timeout. */
+      signal (SIGALRM, SIG_DFL);
+      return 1;
+    }
+  alarm (timeout);
+  fun (arg);
+
+  /* Preserve errno in case alarm() or signal() modifies it. */
+  saved_errno = errno;
+  alarm (0);
+  signal (SIGALRM, SIG_DFL);
+  errno = saved_errno;
+
+  return 0;
+#endif
+}
+
index 162ddd7042bc6b4eda97e8d13be0118d162f721b..a941c5f9278feb933e7fe069a609132e83392178 100644 (file)
@@ -106,4 +106,6 @@ char *html_quote_string PARAMS ((const char *));
 int determine_screen_width PARAMS ((void));
 int random_number PARAMS ((int));
 
 int determine_screen_width PARAMS ((void));
 int random_number PARAMS ((int));
 
+int run_with_timeout PARAMS ((long, void (*) (void *), void *));
+
 #endif /* UTILS_H */
 #endif /* UTILS_H */