]> sjero.net Git - wget/commitdiff
[svn] Implement connect timeout.
authorhniksic <devnull@localhost>
Fri, 12 Apr 2002 01:14:18 +0000 (18:14 -0700)
committerhniksic <devnull@localhost>
Fri, 12 Apr 2002 01:14:18 +0000 (18:14 -0700)
Published in <sxs1ydld8ha.fsf@florida.arsdigita.de>.

ChangeLog
configure.in
src/ChangeLog
src/config.h.in
src/connect.c

index 6c00d87dc767436e56c45a00f9a7187349e7b8af..dd6d69ca5e7229ef00e09af03fe9613d096d411f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2002-04-12  Hrvoje Niksic  <hniksic@arsdigita.com>
+
+       * configure.in: Check for <setjmp.h>.  Check for sigsetjmp and
+       sigblock.
+
 2002-04-09  Ian Abbott  <abbotti@mev.co.uk>
 
        * windows/config.h.bor: define `HACK_BCC_UTIME_BUG'. Define `utime'
index 64ff665bb5ad22c73d2531daa6bd03a920e5fb0d..3f91f1561a6e9da4ee43fb9ab57c1ccb571bfd70 100644 (file)
@@ -156,7 +156,8 @@ dnl
 dnl Checks for headers
 dnl
 AC_CHECK_HEADERS(string.h stdarg.h unistd.h sys/time.h utime.h sys/utime.h pwd.h)
-AC_CHECK_HEADERS(termios.h sys/ioctl.h sys/select.h sys/utsname.h signal.h)
+AC_CHECK_HEADERS(termios.h sys/ioctl.h sys/select.h sys/utsname.h)
+AC_CHECK_HEADERS(signal.h setjmp.h)
 AC_HEADER_TIME
 
 dnl
@@ -174,8 +175,8 @@ dnl
 AC_FUNC_ALLOCA
 AC_FUNC_MMAP
 AC_CHECK_FUNCS(strdup strstr strcasecmp strncasecmp strpbrk memmove)
-AC_CHECK_FUNCS(gettimeofday mktime strptime)
-AC_CHECK_FUNCS(strerror snprintf vsnprintf select signal symlink access isatty)
+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)
 
 dnl
index 9b0c2005ee30f894fd63e64cc5aec5129841b5c7..65d53e23a439c5b80950dbce73bdaffd54daad4f 100644 (file)
@@ -1,3 +1,11 @@
+2002-04-12  Hrvoje Niksic  <hniksic@arsdigita.com>
+
+       * connect.c (connect_with_timeout): New function.
+       (connect_to_one): Use it.
+
+       * config.h.in: Add stubs for HAVE_SIGSETJMP, HAVE_SIGBLOCK, and
+       HAVE_SETJMP_H.
+
 2002-04-11  Hrvoje Niksic  <hniksic@arsdigita.com>
 
        * log.c: Set WGET_USE_STDARG if __STDC__ is defined and stdarg.h
index 24655b0706c4b7a6b9448b26241a7197e8cfe12c..642b94e067a5ae68488aab481bd5af4c6f5daaf2 100644 (file)
@@ -165,6 +165,12 @@ char *alloca ();
 /* Define if you have the signal function.  */
 #undef HAVE_SIGNAL
 
+/* Define if you have the sigsetjmp function.  */
+#undef HAVE_SIGSETJMP
+
+/* Define if you have the sigblock function.  */
+#undef HAVE_SIGBLOCK
+
 /* Define if you have the gettext function.  */
 #undef HAVE_GETTEXT
 
@@ -201,6 +207,9 @@ char *alloca ();
 /* Define if you have the <signal.h> header file.  */
 #undef HAVE_SIGNAL_H
 
+/* Define if you have the <setjmp.h> header file.  */
+#undef HAVE_SETJMP_H
+
 /* Define if you have the <libintl.h> header file.  */
 #undef HAVE_LIBINTL_H
 
index 110f5cef6e53565249c37ce62c98806fb143fecc..d95ad74f44c72f3efe1d91343b7af0c7876934fe 100644 (file)
@@ -47,6 +47,28 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 # 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 "host.h"
 #include "connect.h"
@@ -84,7 +106,82 @@ resolve_bind_address (void)
   address_list_release (al);
   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)
+
+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)
+{
+  /* 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);
+}
+#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
+   ETIMEDOUT.  */
+
+static int
+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);
 
+  signal (SIGALRM, abort_connect);
+  if (SETJMP (abort_connect_env) != 0)
+    {
+      /* Longjumped out of connect with a timeout. */
+      signal (SIGALRM, SIG_DFL);
+      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;
+}
+#endif /* UNIX_CONNECT_TIMEOUT */
+\f
 /* A kludge, but still better than passing the host name all the way
    to connect_to_one.  */
 static const char *connection_host_name;
@@ -142,7 +239,7 @@ connect_to_one (ip_address *addr, unsigned short port, int silent)
     }
 
   /* Connect the socket to the remote host.  */
-  if (connect (sock, &sa.sa, sockaddr_len ()) < 0)
+  if (connect_with_timeout (sock, &sa.sa, sockaddr_len (), opt.timeout) < 0)
     {
       close (sock);
       sock = -1;