From: Daniel Stenberg Date: Thu, 6 Feb 2025 15:05:56 +0000 (+0100) Subject: asyn-thread: do not allocate thread_data separately X-Git-Tag: curl-8_13_0~488 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d9fc64d3ab289a84548e952183d7eba79ccc846e;p=thirdparty%2Fcurl.git asyn-thread: do not allocate thread_data separately Put the full struct into Curl_async since it will be used for every name resolve anyway. Closes #16241 --- diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c index 640c8a9b65..6caba3ceba 100644 --- a/lib/asyn-ares.c +++ b/lib/asyn-ares.c @@ -351,17 +351,12 @@ void Curl_resolver_kill(struct Curl_easy *data) */ static void destroy_async_data(struct Curl_async *async) { - if(async->tdata) { - struct thread_data *res = async->tdata; - if(res) { - if(res->temp_ai) { - Curl_freeaddrinfo(res->temp_ai); - res->temp_ai = NULL; - } - free(res); - } - async->tdata = NULL; + struct thread_data *res = &async->thdata; + if(res->temp_ai) { + Curl_freeaddrinfo(res->temp_ai); + res->temp_ai = NULL; } + Curl_safefree(res->hostname); } /* @@ -385,7 +380,7 @@ int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks) CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, struct Curl_dns_entry **dns) { - struct thread_data *res = data->state.async.tdata; + struct thread_data *res = &data->state.async.thdata; CURLcode result = CURLE_OK; DEBUGASSERT(dns); @@ -398,8 +393,7 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, /* Now that we have checked for any last minute results above, see if there are any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer expires. */ - if(res - && res->num_pending + if(res->num_pending /* This is only set to non-zero if the timer was started. */ && (res->happy_eyeballs_dns_time.tv_sec || res->happy_eyeballs_dns_time.tv_usec) @@ -419,7 +413,7 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, } #endif - if(res && !res->num_pending) { + if(!res->num_pending) { (void)Curl_addrinfo_callback(data, res->last_status, res->temp_ai); /* temp_ai ownership is moved to the connection, so we need not free-up them */ @@ -589,7 +583,7 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */ struct hostent *hostent) { struct Curl_easy *data = (struct Curl_easy *)arg; - struct thread_data *res; + struct thread_data *res = &data->state.async.thdata; #ifdef HAVE_CARES_CALLBACK_TIMEOUTS (void)timeouts; /* ignored */ @@ -600,80 +594,77 @@ static void query_completed_cb(void *arg, /* (struct connectdata *) */ be valid so only defer it when we know the 'status' says its fine! */ return; - res = data->state.async.tdata; - if(res) { - res->num_pending--; + res->num_pending--; - if(CURL_ASYNC_SUCCESS == status) { - struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.async.port); - if(ai) { - compound_results(res, ai); - } - } - /* A successful result overwrites any previous error */ - if(res->last_status != ARES_SUCCESS) - res->last_status = status; - - /* If there are responses still pending, we presume they must be the - complementary IPv4 or IPv6 lookups that we started in parallel in - Curl_resolver_getaddrinfo() (for Happy Eyeballs). If we have got a - "definitive" response from one of a set of parallel queries, we need to - think about how long we are willing to wait for more responses. */ - if(res->num_pending - /* Only these c-ares status values count as "definitive" for these - purposes. For example, ARES_ENODATA is what we expect when there is - no IPv6 entry for a domain name, and that is not a reason to get more - aggressive in our timeouts for the other response. Other errors are - either a result of bad input (which should affect all parallel - requests), local or network conditions, non-definitive server - responses, or us cancelling the request. */ - && (status == ARES_SUCCESS || status == ARES_ENOTFOUND)) { - /* Right now, there can only be up to two parallel queries, so do not - bother handling any other cases. */ - DEBUGASSERT(res->num_pending == 1); - - /* it is possible that one of these parallel queries could succeed - quickly, but the other could always fail or timeout (when we are - talking to a pool of DNS servers that can only successfully resolve - IPv4 address, for example). - - it is also possible that the other request could always just take - longer because it needs more time or only the second DNS server can - fulfill it successfully. But, to align with the philosophy of Happy - Eyeballs, we do not want to wait _too_ long or users will think - requests are slow when IPv6 lookups do not actually work (but IPv4 - ones do). - - So, now that we have a usable answer (some IPv4 addresses, some IPv6 - addresses, or "no such domain"), we start a timeout for the remaining - pending responses. Even though it is typical that this resolved - request came back quickly, that needn't be the case. It might be that - this completing request did not get a result from the first DNS - server or even the first round of the whole DNS server pool. So it - could already be quite some time after we issued the DNS queries in - the first place. Without modifying c-ares, we cannot know exactly - where in its retry cycle we are. We could guess based on how much - time has gone by, but it does not really matter. Happy Eyeballs tells - us that, given usable information in hand, we simply do not want to - wait "too much longer" after we get a result. - - We simply wait an additional amount of time equal to the default - c-ares query timeout. That is enough time for a typical parallel - response to arrive without being "too long". Even on a network - where one of the two types of queries is failing or timing out - constantly, this will usually mean we wait a total of the default - c-ares timeout (5 seconds) plus the round trip time for the successful - request, which seems bearable. The downside is that c-ares might race - with us to issue one more retry just before we give up, but it seems - better to "waste" that request instead of trying to guess the perfect - timeout to prevent it. After all, we do not even know where in the - c-ares retry cycle each request is. - */ - res->happy_eyeballs_dns_time = Curl_now(); - Curl_expire(data, HAPPY_EYEBALLS_DNS_TIMEOUT, - EXPIRE_HAPPY_EYEBALLS_DNS); + if(CURL_ASYNC_SUCCESS == status) { + struct Curl_addrinfo *ai = Curl_he2ai(hostent, data->state.async.port); + if(ai) { + compound_results(res, ai); } } + /* A successful result overwrites any previous error */ + if(res->last_status != ARES_SUCCESS) + res->last_status = status; + + /* If there are responses still pending, we presume they must be the + complementary IPv4 or IPv6 lookups that we started in parallel in + Curl_resolver_getaddrinfo() (for Happy Eyeballs). If we have got a + "definitive" response from one of a set of parallel queries, we need to + think about how long we are willing to wait for more responses. */ + if(res->num_pending + /* Only these c-ares status values count as "definitive" for these + purposes. For example, ARES_ENODATA is what we expect when there is + no IPv6 entry for a domain name, and that is not a reason to get more + aggressive in our timeouts for the other response. Other errors are + either a result of bad input (which should affect all parallel + requests), local or network conditions, non-definitive server + responses, or us cancelling the request. */ + && (status == ARES_SUCCESS || status == ARES_ENOTFOUND)) { + /* Right now, there can only be up to two parallel queries, so do not + bother handling any other cases. */ + DEBUGASSERT(res->num_pending == 1); + + /* it is possible that one of these parallel queries could succeed + quickly, but the other could always fail or timeout (when we are + talking to a pool of DNS servers that can only successfully resolve + IPv4 address, for example). + + it is also possible that the other request could always just take + longer because it needs more time or only the second DNS server can + fulfill it successfully. But, to align with the philosophy of Happy + Eyeballs, we do not want to wait _too_ long or users will think + requests are slow when IPv6 lookups do not actually work (but IPv4 + ones do). + + So, now that we have a usable answer (some IPv4 addresses, some IPv6 + addresses, or "no such domain"), we start a timeout for the remaining + pending responses. Even though it is typical that this resolved + request came back quickly, that needn't be the case. It might be that + this completing request did not get a result from the first DNS + server or even the first round of the whole DNS server pool. So it + could already be quite some time after we issued the DNS queries in + the first place. Without modifying c-ares, we cannot know exactly + where in its retry cycle we are. We could guess based on how much + time has gone by, but it does not really matter. Happy Eyeballs tells + us that, given usable information in hand, we simply do not want to + wait "too much longer" after we get a result. + + We simply wait an additional amount of time equal to the default + c-ares query timeout. That is enough time for a typical parallel + response to arrive without being "too long". Even on a network + where one of the two types of queries is failing or timing out + constantly, this will usually mean we wait a total of the default + c-ares timeout (5 seconds) plus the round trip time for the successful + request, which seems bearable. The downside is that c-ares might race + with us to issue one more retry just before we give up, but it seems + better to "waste" that request instead of trying to guess the perfect + timeout to prevent it. After all, we do not even know where in the + c-ares retry cycle each request is. + */ + res->happy_eyeballs_dns_time = Curl_now(); + Curl_expire(data, HAPPY_EYEBALLS_DNS_TIMEOUT, + EXPIRE_HAPPY_EYEBALLS_DNS); + } } #else /* c-ares 1.16.0 or later */ @@ -756,7 +747,7 @@ static void addrinfo_cb(void *arg, int status, int timeouts, struct ares_addrinfo *result) { struct Curl_easy *data = (struct Curl_easy *)arg; - struct thread_data *res = data->state.async.tdata; + struct thread_data *res = &data->state.async.thdata; (void)timeouts; if(ARES_SUCCESS == status) { res->temp_ai = ares2addr(result->nodes); @@ -781,87 +772,86 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data, int port, int *waitp) { - struct thread_data *res = NULL; - size_t namelen = strlen(hostname); + struct thread_data *res = &data->state.async.thdata; *waitp = 0; /* default to synchronous response */ - res = calloc(1, sizeof(struct thread_data) + namelen); - if(res) { - strcpy(res->hostname, hostname); - data->state.async.hostname = res->hostname; - data->state.async.port = port; - data->state.async.done = FALSE; /* not done */ - data->state.async.status = 0; /* clear */ - data->state.async.dns = NULL; /* clear */ - data->state.async.tdata = res; + res->hostname = strdup(hostname); + if(!res->hostname) + return NULL; + + data->state.async.hostname = res->hostname; + data->state.async.port = port; + data->state.async.done = FALSE; /* not done */ + data->state.async.status = 0; /* clear */ + data->state.async.dns = NULL; /* clear */ - /* initial status - failed */ - res->last_status = ARES_ENOTFOUND; + /* initial status - failed */ + res->last_status = ARES_ENOTFOUND; #ifdef HAVE_CARES_GETADDRINFO - { - struct ares_addrinfo_hints hints; - char service[12]; - int pf = PF_INET; - memset(&hints, 0, sizeof(hints)); + { + struct ares_addrinfo_hints hints; + char service[12]; + int pf = PF_INET; + memset(&hints, 0, sizeof(hints)); #ifdef CURLRES_IPV6 - if((data->conn->ip_version != CURL_IPRESOLVE_V4) && - Curl_ipv6works(data)) { - /* The stack seems to be IPv6-enabled */ - if(data->conn->ip_version == CURL_IPRESOLVE_V6) - pf = PF_INET6; - else - pf = PF_UNSPEC; - } -#endif /* CURLRES_IPV6 */ - hints.ai_family = pf; - hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP) ? - SOCK_STREAM : SOCK_DGRAM; - /* Since the service is a numerical one, set the hint flags - * accordingly to save a call to getservbyname in inside C-Ares - */ - hints.ai_flags = ARES_AI_NUMERICSERV; - msnprintf(service, sizeof(service), "%d", port); - res->num_pending = 1; - ares_getaddrinfo((ares_channel)data->state.async.resolver, hostname, - service, &hints, addrinfo_cb, data); + if((data->conn->ip_version != CURL_IPRESOLVE_V4) && + Curl_ipv6works(data)) { + /* The stack seems to be IPv6-enabled */ + if(data->conn->ip_version == CURL_IPRESOLVE_V6) + pf = PF_INET6; + else + pf = PF_UNSPEC; } +#endif /* CURLRES_IPV6 */ + hints.ai_family = pf; + hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP) ? + SOCK_STREAM : SOCK_DGRAM; + /* Since the service is a numerical one, set the hint flags + * accordingly to save a call to getservbyname in inside C-Ares + */ + hints.ai_flags = ARES_AI_NUMERICSERV; + msnprintf(service, sizeof(service), "%d", port); + res->num_pending = 1; + ares_getaddrinfo((ares_channel)data->state.async.resolver, hostname, + service, &hints, addrinfo_cb, data); + } #else #ifdef HAVE_CARES_IPV6 - if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) { - /* The stack seems to be IPv6-enabled */ - res->num_pending = 2; - - /* areschannel is already setup in the Curl_open() function */ - ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, - PF_INET, query_completed_cb, data); - ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, - PF_INET6, query_completed_cb, data); - } - else + if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) { + /* The stack seems to be IPv6-enabled */ + res->num_pending = 2; + + /* areschannel is already setup in the Curl_open() function */ + ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, + PF_INET, query_completed_cb, data); + ares_gethostbyname((ares_channel)data->state.async.resolver, hostname, + PF_INET6, query_completed_cb, data); + } + else #endif - { - res->num_pending = 1; + { + res->num_pending = 1; - /* areschannel is already setup in the Curl_open() function */ - ares_gethostbyname((ares_channel)data->state.async.resolver, - hostname, PF_INET, - query_completed_cb, data); - } + /* areschannel is already setup in the Curl_open() function */ + ares_gethostbyname((ares_channel)data->state.async.resolver, + hostname, PF_INET, + query_completed_cb, data); + } #endif #ifdef USE_HTTPSRR_ARES - { - res->num_pending++; /* one more */ - memset(&res->hinfo, 0, sizeof(struct Curl_https_rrinfo)); - ares_query_dnsrec((ares_channel)data->state.async.resolver, - hostname, ARES_CLASS_IN, - ARES_REC_TYPE_HTTPS, - Curl_dnsrec_done_cb, data, NULL); - } -#endif - *waitp = 1; /* expect asynchronous response */ + { + res->num_pending++; /* one more */ + memset(&res->hinfo, 0, sizeof(struct Curl_https_rrinfo)); + ares_query_dnsrec((ares_channel)data->state.async.resolver, + hostname, ARES_CLASS_IN, + ARES_REC_TYPE_HTTPS, + Curl_dnsrec_done_cb, data, NULL); } +#endif + *waitp = 1; /* expect asynchronous response */ + return NULL; /* no struct yet */ } diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c index f98941596e..1fe88f9b0b 100644 --- a/lib/asyn-thread.c +++ b/lib/asyn-thread.c @@ -156,7 +156,7 @@ static bool init_resolve_thread(struct Curl_easy *data, static struct thread_sync_data *conn_thread_sync_data(struct Curl_easy *data) { - return &(data->state.async.tdata->tsd); + return &(data->state.async.thdata.tsd); } /* Destroy resolver thread synchronization data */ @@ -190,15 +190,15 @@ void destroy_thread_sync_data(struct thread_sync_data *tsd) /* Initialize resolver thread synchronization data */ static int init_thread_sync_data(struct thread_data *td, - const char *hostname, - int port, - const struct addrinfo *hints) + const char *hostname, + int port, + const struct addrinfo *hints) { struct thread_sync_data *tsd = &td->tsd; memset(tsd, 0, sizeof(*tsd)); - tsd->td = td; + td->init = TRUE; tsd->port = port; /* Treat the request as done until the thread actually starts so any early * cleanup gets done properly. @@ -278,8 +278,8 @@ unsigned int #endif CURL_STDCALL getaddrinfo_thread(void *arg) { - struct thread_sync_data *tsd = (struct thread_sync_data *)arg; - struct thread_data *td = tsd->td; + struct thread_data *td = arg; + struct thread_sync_data *tsd = &td->tsd; char service[12]; int rc; @@ -301,7 +301,6 @@ CURL_STDCALL getaddrinfo_thread(void *arg) /* too late, gotta clean up the mess */ Curl_mutex_release(tsd->mtx); destroy_thread_sync_data(tsd); - free(td); } else { #ifndef CURL_DISABLE_SOCKETPAIR @@ -338,8 +337,8 @@ unsigned int #endif CURL_STDCALL gethostbyname_thread(void *arg) { - struct thread_sync_data *tsd = (struct thread_sync_data *)arg; - struct thread_data *td = tsd->td; + struct thread_data *td = arg; + struct thread_sync_data *tsd = &td->tsd; tsd->res = Curl_ipv4_resolve_r(tsd->hostname, tsd->port); @@ -354,7 +353,6 @@ CURL_STDCALL gethostbyname_thread(void *arg) /* too late, gotta clean up the mess */ Curl_mutex_release(tsd->mtx); destroy_thread_sync_data(tsd); - free(td); } else { tsd->done = TRUE; @@ -371,20 +369,19 @@ CURL_STDCALL gethostbyname_thread(void *arg) */ static void destroy_async_data(struct Curl_easy *data) { - struct Curl_async *async; - DEBUGASSERT(data); - async = &data->state.async; - DEBUGASSERT(async); - if(async->tdata) { - struct thread_data *td = async->tdata; + struct Curl_async *async = &data->state.async; + struct thread_data *td = &async->thdata; + if(td->init) { bool done; #ifndef CURL_DISABLE_SOCKETPAIR curl_socket_t sock_rd = td->tsd.sock_pair[0]; #endif #ifdef USE_HTTPSRR_ARES - if(data->state.async.tdata->channel) - ares_destroy(data->state.async.tdata->channel); + if(data->state.async.thdata.channel) { + ares_destroy(data->state.async.thdata.channel); + data->state.async.thdata.channel = NULL; + } #endif /* * if the thread is still blocking in the resolve syscall, detach it and @@ -403,8 +400,6 @@ static void destroy_async_data(struct Curl_easy *data) Curl_thread_join(&td->thread_hnd); destroy_thread_sync_data(&td->tsd); - - free(async->tdata); } #ifndef CURL_DISABLE_SOCKETPAIR /* @@ -414,24 +409,23 @@ static void destroy_async_data(struct Curl_easy *data) Curl_multi_closed(data, sock_rd); wakeup_close(sock_rd); #endif - } - async->tdata = NULL; - free(async->hostname); - async->hostname = NULL; + td->init = FALSE; + } + Curl_safefree(async->hostname); } #ifdef USE_HTTPSRR_ARES static CURLcode resolve_httpsrr(struct Curl_easy *data, - struct Curl_async *asp) + struct Curl_async *async) { - int status = ares_init_options(&asp->tdata->channel, NULL, 0); + int status = ares_init_options(&async->thdata.channel, NULL, 0); if(status != ARES_SUCCESS) return CURLE_FAILED_INIT; - memset(&asp->tdata->hinfo, 0, sizeof(struct Curl_https_rrinfo)); - ares_query_dnsrec(asp->tdata->channel, - asp->hostname, ARES_CLASS_IN, + memset(&async->thdata.hinfo, 0, sizeof(struct Curl_https_rrinfo)); + ares_query_dnsrec(async->thdata.channel, + async->hostname, ARES_CLASS_IN, ARES_REC_TYPE_HTTPS, Curl_dnsrec_done_cb, data, NULL); @@ -449,38 +443,33 @@ static bool init_resolve_thread(struct Curl_easy *data, const char *hostname, int port, const struct addrinfo *hints) { - struct thread_data *td = calloc(1, sizeof(struct thread_data)); + struct thread_data *td = &data->state.async.thdata; int err = ENOMEM; - struct Curl_async *asp = &data->state.async; + struct Curl_async *async = &data->state.async; - data->state.async.tdata = td; - if(!td) - goto errno_exit; - - asp->port = port; - asp->done = FALSE; - asp->status = 0; - asp->dns = NULL; + async->port = port; + async->done = FALSE; + async->status = 0; + async->dns = NULL; td->thread_hnd = curl_thread_t_null; if(!init_thread_sync_data(td, hostname, port, hints)) { - asp->tdata = NULL; free(td); goto errno_exit; } - free(asp->hostname); - asp->hostname = strdup(hostname); - if(!asp->hostname) + free(async->hostname); + async->hostname = strdup(hostname); + if(!async->hostname) goto err_exit; /* The thread will set this TRUE when complete. */ td->tsd.done = FALSE; #ifdef HAVE_GETADDRINFO - td->thread_hnd = Curl_thread_create(getaddrinfo_thread, &td->tsd); + td->thread_hnd = Curl_thread_create(getaddrinfo_thread, td); #else - td->thread_hnd = Curl_thread_create(gethostbyname_thread, &td->tsd); + td->thread_hnd = Curl_thread_create(gethostbyname_thread, td); #endif if(td->thread_hnd == curl_thread_t_null) { @@ -490,7 +479,7 @@ static bool init_resolve_thread(struct Curl_easy *data, goto err_exit; } #ifdef USE_HTTPSRR_ARES - if(resolve_httpsrr(data, asp)) + if(resolve_httpsrr(data, async)) infof(data, "Failed HTTPS RR operation"); #endif return TRUE; @@ -514,7 +503,7 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data, CURLcode result = CURLE_OK; DEBUGASSERT(data); - td = data->state.async.tdata; + td = &data->state.async.thdata; DEBUGASSERT(td); DEBUGASSERT(td->thread_hnd != curl_thread_t_null); @@ -550,13 +539,12 @@ static CURLcode thread_wait_resolv(struct Curl_easy *data, */ void Curl_resolver_kill(struct Curl_easy *data) { - struct thread_data *td = data->state.async.tdata; + struct thread_data *td = &data->state.async.thdata; /* If we are still resolving, we must wait for the threads to fully clean up, unfortunately. Otherwise, we can simply cancel to clean up any resolver data. */ - if(td && td->thread_hnd != curl_thread_t_null - && (data->set.quick_exit != 1L)) + if((td->thread_hnd != curl_thread_t_null) && !data->set.quick_exit) (void)thread_wait_resolv(data, NULL, FALSE); else Curl_resolver_cancel(data); @@ -589,7 +577,7 @@ CURLcode Curl_resolver_wait_resolv(struct Curl_easy *data, CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, struct Curl_dns_entry **entry) { - struct thread_data *td = data->state.async.tdata; + struct thread_data *td = &data->state.async.thdata; bool done = FALSE; DEBUGASSERT(entry); @@ -600,7 +588,7 @@ CURLcode Curl_resolver_is_resolved(struct Curl_easy *data, return CURLE_COULDNT_RESOLVE_HOST; } #ifdef USE_HTTPSRR_ARES - if(Curl_ares_perform(data->state.async.tdata->channel, 0) < 0) + if(Curl_ares_perform(data->state.async.thdata.channel, 0) < 0) return CURLE_UNRECOVERABLE_POLL; #endif @@ -662,7 +650,7 @@ int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks) timediff_t ms; struct resdata *reslv = (struct resdata *)data->state.async.resolver; #ifndef CURL_DISABLE_SOCKETPAIR - struct thread_data *td = data->state.async.tdata; + struct thread_data *td = &data->state.async.thdata; #endif #if !defined(CURL_DISABLE_SOCKETPAIR) || defined(USE_HTTPSRR_ARES) int socketi = 0; @@ -671,8 +659,8 @@ int Curl_resolver_getsock(struct Curl_easy *data, curl_socket_t *socks) #endif #ifdef USE_HTTPSRR_ARES - if(data->state.async.tdata && data->state.async.tdata->channel) { - ret_val = Curl_ares_getsock(data, data->state.async.tdata->channel, socks); + if(data->state.async.thdata.channel) { + ret_val = Curl_ares_getsock(data, data->state.async.thdata.channel, socks); for(socketi = 0; socketi < (MAX_SOCKSPEREASYHANDLE - 1); socketi++) if(!ARES_GETSOCK_READABLE(ret_val, socketi) && !ARES_GETSOCK_WRITABLE(ret_val, socketi)) diff --git a/lib/asyn.h b/lib/asyn.h index 5a21329cf3..d22378f06c 100644 --- a/lib/asyn.h +++ b/lib/asyn.h @@ -49,7 +49,6 @@ struct thread_sync_data { #ifdef HAVE_GETADDRINFO struct addrinfo hints; #endif - struct thread_data *td; /* for thread-self cleanup */ int port; int sock_error; bool done; @@ -64,6 +63,7 @@ struct thread_data { struct Curl_https_rrinfo hinfo; ares_channel channel; #endif + bool init; }; #elif defined(CURLRES_ARES) /* CURLRES_THREADED */ @@ -79,7 +79,7 @@ struct thread_data { #ifdef USE_HTTPSRR struct Curl_https_rrinfo hinfo; #endif - char hostname[1]; + char *hostname; }; #endif /* CURLRES_ARES */ diff --git a/lib/httpsrr.c b/lib/httpsrr.c index 9884b92580..3072f60bb1 100644 --- a/lib/httpsrr.c +++ b/lib/httpsrr.c @@ -100,7 +100,7 @@ static void httpsrr_opt(struct Curl_easy *data, size_t len = 0; const unsigned char *val = NULL; unsigned short code; - struct thread_data *res = data->state.async.tdata; + struct thread_data *res = &data->state.async.thdata; struct Curl_https_rrinfo *hi = &res->hinfo; code = ares_dns_rr_get_opt(rr, key, idx, &val, &len); @@ -138,7 +138,7 @@ void Curl_dnsrec_done_cb(void *arg, ares_status_t status, struct Curl_easy *data = arg; size_t i; #ifdef CURLRES_ARES - struct thread_data *res = data->state.async.tdata; + struct thread_data *res = &data->state.async.thdata; res->num_pending--; #endif diff --git a/lib/urldata.h b/lib/urldata.h index d9acb2b7bf..58b9d7983a 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -568,7 +568,9 @@ struct hostname { struct Curl_async { char *hostname; struct Curl_dns_entry *dns; - struct thread_data *tdata; +#ifdef CURLRES_ASYNCH + struct thread_data thdata; +#endif void *resolver; /* resolver state, if it is used in the URL state - ares_channel e.g. */ int port;