diff options
author | Daniel Stenberg <daniel@haxx.se> | 2018-03-22 17:59:58 +0100 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2018-03-24 00:02:25 +0100 |
commit | 67636222f42b7db146b963deb577a981b4fcdfa2 (patch) | |
tree | 28a622aa1bd61dc74efbacc07b440e02b88e7d18 | |
parent | b6e484dc36a2681c0991a274398f917e74517053 (diff) |
threaded resolver: track resolver time and set suitable timeout values
In order to make curl_multi_timeout() return suitable "sleep" times even
when there's no socket to wait for while the name is being resolved in a
helper thread.
It will increases the timeouts as time passes.
Closes #2419
-rw-r--r-- | lib/asyn-thread.c | 67 |
1 files changed, 39 insertions, 28 deletions
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c index 1ac3fc809..b11fab246 100644 --- a/lib/asyn-thread.c +++ b/lib/asyn-thread.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -79,6 +79,10 @@ #include "curl_memory.h" #include "memdebug.h" +struct resdata { + struct curltime start; +}; + /* * Curl_resolver_global_init() * Called from curl_global_init() to initialize global resolver environment. @@ -102,11 +106,13 @@ void Curl_resolver_global_cleanup(void) * Curl_resolver_init() * Called from curl_easy_init() -> Curl_open() to initialize resolver * URL-state specific environment ('resolver' member of the UrlState - * structure). Does nothing here. + * structure). */ CURLcode Curl_resolver_init(void **resolver) { - (void)resolver; + *resolver = calloc(1, sizeof(struct resdata)); + if(!*resolver) + return CURLE_OUT_OF_MEMORY; return CURLE_OK; } @@ -114,24 +120,22 @@ CURLcode Curl_resolver_init(void **resolver) * Curl_resolver_cleanup() * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver * URL-state specific environment ('resolver' member of the UrlState - * structure). Does nothing here. + * structure). */ void Curl_resolver_cleanup(void *resolver) { - (void)resolver; + free(resolver); } /* * Curl_resolver_duphandle() * Called from curl_easy_duphandle() to duplicate resolver URL state-specific - * environment ('resolver' member of the UrlState structure). Does nothing - * here. + * environment ('resolver' member of the UrlState structure). */ int Curl_resolver_duphandle(void **to, void *from) { - (void)to; (void)from; - return CURLE_OK; + return Curl_resolver_init(to); } static void destroy_async_data(struct Curl_async *); @@ -561,9 +565,22 @@ int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *socks, int numsocks) { - (void)conn; + time_t milli; + timediff_t ms; + struct Curl_easy *data = conn->data; + struct resdata *reslv = (struct resdata *)data->state.resolver; (void)socks; (void)numsocks; + ms = Curl_timediff(Curl_now(), reslv->start); + if(ms < 10) + milli = ms/3; + else if(ms <= 50) + milli = 10; + else if(ms <= 250) + milli = 50; + else + milli = 200; + Curl_expire(data, milli, EXPIRE_ASYNC_NAME); return 0; } @@ -577,6 +594,8 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, int *waitp) { struct in_addr in; + struct Curl_easy *data = conn->data; + struct resdata *reslv = (struct resdata *)data->state.resolver; *waitp = 0; /* default to synchronous response */ @@ -584,14 +603,17 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, /* This is a dotted IP address 123.123.123.123-style */ return Curl_ip2addr(AF_INET, &in, hostname, port); + reslv->start = Curl_now(); + /* fire up a new resolver thread! */ if(init_resolve_thread(conn, hostname, port, NULL)) { *waitp = 1; /* expect asynchronous response */ return NULL; } - /* fall-back to blocking version */ - return Curl_ipv4_resolve_r(hostname, port); + failf(conn->data, "getaddrinfo() thread failed\n"); + + return NULL; } #else /* !HAVE_GETADDRINFO */ @@ -605,10 +627,10 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, int *waitp) { struct addrinfo hints; - Curl_addrinfo *res; - int error; char sbuf[12]; int pf = PF_INET; + struct Curl_easy *data = conn->data; + struct resdata *reslv = (struct resdata *)data->state.resolver; *waitp = 0; /* default to synchronous response */ @@ -658,27 +680,16 @@ Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, snprintf(sbuf, sizeof(sbuf), "%d", port); + reslv->start = Curl_now(); /* fire up a new resolver thread! */ if(init_resolve_thread(conn, hostname, port, &hints)) { *waitp = 1; /* expect asynchronous response */ return NULL; } - /* fall-back to blocking version */ - infof(conn->data, "init_resolve_thread() failed for %s; %s\n", - hostname, Curl_strerror(conn, errno)); - - error = Curl_getaddrinfo_ex(hostname, sbuf, &hints, &res); - if(error) { - infof(conn->data, "getaddrinfo() failed for %s:%d; %s\n", - hostname, port, Curl_strerror(conn, SOCKERRNO)); - return NULL; - } - else { - Curl_addrinfo_set_port(res, port); - } + failf(data, "getaddrinfo() thread failed to start\n"); + return NULL; - return res; } #endif /* !HAVE_GETADDRINFO */ |