wget: add support for connect timeout
authorLauri Kasanen <curaga@operamail.com>
Sat, 12 Oct 2013 19:47:07 +0000 (21:47 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sat, 12 Oct 2013 19:47:07 +0000 (21:47 +0200)
function                                             old     new   delta
open_socket                                           33      64     +31
wget_main                                           2182    2194     +12

Signed-off-by: Lauri Kasanen <curaga@operamail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
networking/Config.src
networking/wget.c

index e1ae0c9d54d642ffc3fd17d11eb61e212f5de010..ca0ddcdd97bc0a3340e52e3ea6d3af08a257ab2a 100644 (file)
@@ -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"
index 5dac2b5001fcb657939139689259aa73b122be5b..a32f8522939a16897e38912a91373cece8a30967 100644 (file)
@@ -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 */