[svn] Implement connect timeout.

Published in <sxs1ydld8ha.fsf@florida.arsdigita.de>.
This commit is contained in:
hniksic 2002-04-11 18:14:18 -07:00
parent fca8dcf829
commit 0cd669109b
5 changed files with 124 additions and 4 deletions

View File

@ -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'

View 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

View 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

View 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

View 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;
}
#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;