commit d074b416f8d3ca6b6ae7b44d17e204ea8d81e7a0 Author: Lauri Kasanen Date: Sat Oct 12 21:47:07 2013 +0200 wget: add support for connect timeout function old new delta open_socket 33 64 +31 wget_main 2182 2194 +12 Signed-off-by: Lauri Kasanen Signed-off-by: Denys Vlasenko diff --git a/networking/Config.src b/networking/Config.src index e1ae0c9..ca0ddcd 100644 --- a/networking/Config.src +++ b/networking/Config.src @@ -970,16 +970,18 @@ config FEATURE_WGET_LONG_OPTIONS Support long options for the wget applet. config FEATURE_WGET_TIMEOUT - bool "Enable read timeout option -T SEC" + bool "Enable timeout option -T SEC" default y depends on WGET help - Supports network read timeout for wget, so that wget will give - up and timeout when reading network data, through the -T command - line option. Currently only network data read timeout is - supported (i.e., timeout is not applied to the DNS nor TCP - connection initialization). When FEATURE_WGET_LONG_OPTIONS is - also enabled, the --timeout option will work in addition to -T. + Supports network read and connect timeouts for wget, + so that wget will give up and timeout, through the -T + command line option. + + Currently only connect and network data read timeout are + supported (i.e., timeout is not applied to the DNS query). When + FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option + will work in addition to -T. config ZCIP bool "zcip" diff --git a/networking/wget.c b/networking/wget.c index 5dac2b5..a32f852 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -72,6 +72,7 @@ struct globals { const char *user_agent; /* "User-Agent" header field */ #if ENABLE_FEATURE_WGET_TIMEOUT unsigned timeout_seconds; + bool connecting; #endif int output_fd; int o_flags; @@ -87,7 +88,6 @@ struct globals { #define G (*ptr_to_globals) #define INIT_G() do { \ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ - IF_FEATURE_WGET_TIMEOUT(G.timeout_seconds = 900;) \ } while (0) @@ -195,13 +195,27 @@ static char* sanitize_string(char *s) return s; } +#if ENABLE_FEATURE_WGET_TIMEOUT +static void alarm_handler(int sig UNUSED_PARAM) +{ + /* This is theoretically unsafe (uses stdio and malloc in signal handler) */ + if (G.connecting) + bb_error_msg_and_die("download timed out"); +} +#endif + static FILE *open_socket(len_and_sockaddr *lsa) { + int fd; FILE *fp; + IF_FEATURE_WGET_TIMEOUT(alarm(G.timeout_seconds); G.connecting = 1;) + fd = xconnect_stream(lsa); + IF_FEATURE_WGET_TIMEOUT(G.connecting = 0;) + /* glibc 2.4 seems to try seeking on it - ??! */ /* hopefully it understands what ESPIPE means... */ - fp = fdopen(xconnect_stream(lsa), "r+"); + fp = fdopen(fd, "r+"); if (fp == NULL) bb_perror_msg_and_die(bb_msg_memory_exhausted); @@ -209,6 +223,7 @@ static FILE *open_socket(len_and_sockaddr *lsa) } /* Returns '\n' if it was seen, else '\0'. Trims at first '\r' or '\n' */ +/* FIXME: does not respect FEATURE_WGET_TIMEOUT and -T N: */ static char fgets_and_trim(FILE *fp) { char c; @@ -944,7 +959,10 @@ int wget_main(int argc UNUSED_PARAM, char **argv) INIT_G(); - IF_FEATURE_WGET_TIMEOUT(G.timeout_seconds = 900;) +#if ENABLE_FEATURE_WGET_TIMEOUT + G.timeout_seconds = 900; + signal(SIGALRM, alarm_handler); +#endif G.proxy_flag = "on"; /* use proxies if env vars are set */ G.user_agent = "Wget"; /* "User-Agent" header field */