mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
[svn] Generalize connect_with_timeout into run_with_timeout.
Published in <sxs4rifxndi.fsf@florida.arsdigita.de>.
This commit is contained in:
parent
5390ada318
commit
f3d3a50a56
@ -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>
|
2002-04-13 Hrvoje Niksic <hniksic@arsdigita.com>
|
||||||
|
|
||||||
* url.c (getproxy): Accept a struct url argument. This obviates
|
* url.c (getproxy): Accept a struct url argument. This obviates
|
||||||
|
@ -47,29 +47,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||||||
# include <sys/select.h>
|
# include <sys/select.h>
|
||||||
#endif /* HAVE_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 "host.h"
|
||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
|
|
||||||
@ -107,45 +86,19 @@ resolve_bind_address (void)
|
|||||||
bind_address_resolved = 1;
|
bind_address_resolved = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef UNIX_CONNECT_TIMEOUT
|
struct cwt_context {
|
||||||
static int
|
int fd;
|
||||||
connect_with_timeout (int fd, const struct sockaddr *addr, int addrlen,
|
const struct sockaddr *addr;
|
||||||
int timeout)
|
int addrlen;
|
||||||
|
int result;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
connect_with_timeout_callback (void *arg)
|
||||||
{
|
{
|
||||||
return connect (fd, addr, addrlen);
|
struct cwt_context *ctx = (struct cwt_context *)arg;
|
||||||
|
ctx->result = connect (ctx->fd, ctx->addr, ctx->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
|
/* Like connect, but specifies a timeout. If connecting takes longer
|
||||||
than TIMEOUT seconds, -1 is returned and errno is set to
|
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,
|
connect_with_timeout (int fd, const struct sockaddr *addr, int addrlen,
|
||||||
int timeout)
|
int timeout)
|
||||||
{
|
{
|
||||||
int result, saved_errno;
|
struct cwt_context ctx;
|
||||||
|
ctx.fd = fd;
|
||||||
|
ctx.addr = addr;
|
||||||
|
ctx.addrlen = addrlen;
|
||||||
|
|
||||||
if (timeout == 0)
|
if (run_with_timeout (timeout, connect_with_timeout_callback, &ctx))
|
||||||
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;
|
errno = ETIMEDOUT;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (ctx.result == -1 && errno == EINTR)
|
||||||
alarm (timeout);
|
errno = ETIMEDOUT;
|
||||||
result = connect (fd, addr, addrlen);
|
return ctx.result;
|
||||||
|
|
||||||
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
|
/* A kludge, but still better than passing the host name all the way
|
||||||
to connect_to_one. */
|
to connect_to_one. */
|
||||||
|
@ -551,6 +551,10 @@ lookup_host (const char *host, int silent)
|
|||||||
if (!silent)
|
if (!silent)
|
||||||
logprintf (LOG_VERBOSE, _("Resolving %s... "), host);
|
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
|
#ifdef INET6
|
||||||
{
|
{
|
||||||
struct addrinfo hints, *ai;
|
struct addrinfo hints, *ai;
|
||||||
|
91
src/utils.c
91
src/utils.c
@ -59,6 +59,27 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||||||
# include <termios.h>
|
# include <termios.h>
|
||||||
#endif
|
#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 "wget.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "fnmatch.h"
|
#include "fnmatch.h"
|
||||||
@ -1757,3 +1778,73 @@ debug_test_md5 (char *buf)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -106,4 +106,6 @@ char *html_quote_string PARAMS ((const char *));
|
|||||||
int determine_screen_width PARAMS ((void));
|
int determine_screen_width PARAMS ((void));
|
||||||
int random_number PARAMS ((int));
|
int random_number PARAMS ((int));
|
||||||
|
|
||||||
|
int run_with_timeout PARAMS ((long, void (*) (void *), void *));
|
||||||
|
|
||||||
#endif /* UTILS_H */
|
#endif /* UTILS_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user