From 8a20b2f66f69a9ca6efec77d1a0eb2cc24550002 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 22 Mar 2018 17:59:58 +0100 Subject: thread 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 slowly increase the timeouts as time passes. --- lib/asyn-thread.c | 67 ++++++++++++++++++++++++++++++++----------------------- 1 file 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, , et al. + * Copyright (C) 1998 - 2018, Daniel Stenberg, , 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 */ -- cgit v1.2.1