From: hniksic Date: Fri, 12 Apr 2002 01:14:18 +0000 (-0700) Subject: [svn] Implement connect timeout. X-Git-Tag: v1.13~1813 X-Git-Url: http://sjero.net/git/?p=wget;a=commitdiff_plain;h=0cd669109b6561b81c0ce8a6ea62c6a5fb2ff76b [svn] Implement connect timeout. Published in . --- diff --git a/ChangeLog b/ChangeLog index 6c00d87d..dd6d69ca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2002-04-12 Hrvoje Niksic + + * configure.in: Check for . Check for sigsetjmp and + sigblock. + 2002-04-09 Ian Abbott * windows/config.h.bor: define `HACK_BCC_UTIME_BUG'. Define `utime' diff --git a/configure.in b/configure.in index 64ff665b..3f91f156 100644 --- a/configure.in +++ b/configure.in @@ -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 diff --git a/src/ChangeLog b/src/ChangeLog index 9b0c2005..65d53e23 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +2002-04-12 Hrvoje Niksic + + * 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 * log.c: Set WGET_USE_STDARG if __STDC__ is defined and stdarg.h diff --git a/src/config.h.in b/src/config.h.in index 24655b07..642b94e0 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -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 header file. */ #undef HAVE_SIGNAL_H +/* Define if you have the header file. */ +#undef HAVE_SETJMP_H + /* Define if you have the header file. */ #undef HAVE_LIBINTL_H diff --git a/src/connect.c b/src/connect.c index 110f5cef..d95ad74f 100644 --- a/src/connect.c +++ b/src/connect.c @@ -47,6 +47,28 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ # include #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 +#endif +#ifdef HAVE_SETJMP_H +# include +#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; } + +#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 */ + /* 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;