mirror of
https://github.com/curl/curl.git
synced 2026-04-14 21:41:41 +03:00
async-ares: blocking resolve timeout handling, better
Perform the actual timeout calculation in the blocking resolv loop each time in the same way, keeping the logic simpler. The previous version calculated the timeout once, and then reduced it by the elapsed time spent in polling/processing. This is unnecessarily complicated. Closes #20819
This commit is contained in:
parent
bfb79de206
commit
b803dc9f20
1 changed files with 48 additions and 45 deletions
|
|
@ -368,6 +368,32 @@ out:
|
|||
return result;
|
||||
}
|
||||
|
||||
static timediff_t async_ares_poll_timeout(struct async_ares_ctx *ares,
|
||||
timediff_t timeout_ms)
|
||||
{
|
||||
struct timeval *ares_calced, time_buf, max_timeout;
|
||||
int itimeout_ms;
|
||||
|
||||
#if TIMEDIFF_T_MAX > INT_MAX
|
||||
itimeout_ms = (timeout_ms > INT_MAX) ? INT_MAX :
|
||||
((timeout_ms < 0) ? -1 : (int)timeout_ms);
|
||||
#else
|
||||
itimeout_ms = (int)timeout_ms;
|
||||
#endif
|
||||
max_timeout.tv_sec = itimeout_ms / 1000;
|
||||
max_timeout.tv_usec = (itimeout_ms % 1000) * 1000;
|
||||
|
||||
/* c-ares tells us the shortest timeout of any operation on channel */
|
||||
ares_calced = ares_timeout(ares->channel, &max_timeout, &time_buf);
|
||||
/* use the timeout period ares returned to us above if less than one
|
||||
second is left, otherwise use 1000ms to make sure the progress callback
|
||||
gets called frequent enough */
|
||||
if(!ares_calced->tv_sec)
|
||||
return (timediff_t)(ares_calced->tv_usec / 1000);
|
||||
else
|
||||
return 1000;
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_async_await()
|
||||
*
|
||||
|
|
@ -383,67 +409,44 @@ CURLcode Curl_async_await(struct Curl_easy *data,
|
|||
struct Curl_dns_entry **dns)
|
||||
{
|
||||
struct async_ares_ctx *ares = &data->state.async.ares;
|
||||
struct curltime start = *Curl_pgrs_now(data);
|
||||
CURLcode result = CURLE_OK;
|
||||
timediff_t timeout_ms;
|
||||
|
||||
DEBUGASSERT(dns);
|
||||
*dns = NULL; /* clear on entry */
|
||||
|
||||
timeout_ms = Curl_timeleft_ms(data);
|
||||
if(timeout_ms < 0) {
|
||||
/* already expired! */
|
||||
connclose(data->conn, "Timed out before name resolve started");
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
if(!timeout_ms)
|
||||
timeout_ms = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve */
|
||||
|
||||
/* Wait for the name resolve query to complete. */
|
||||
/* Wait for the name resolve query to complete or time out. */
|
||||
while(!result) {
|
||||
struct timeval *real_timeout, time_buf, max_timeout;
|
||||
int itimeout_ms;
|
||||
timediff_t call_timeout_ms;
|
||||
timediff_t timeout_ms;
|
||||
|
||||
#if TIMEDIFF_T_MAX > INT_MAX
|
||||
itimeout_ms = (timeout_ms > INT_MAX) ? INT_MAX : (int)timeout_ms;
|
||||
#else
|
||||
itimeout_ms = (int)timeout_ms;
|
||||
#endif
|
||||
timeout_ms = Curl_timeleft_ms(data);
|
||||
if(!timeout_ms) { /* no applicable timeout from `data`*/
|
||||
timediff_t elapsed_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &start);
|
||||
if(elapsed_ms < (CURL_TIMEOUT_RESOLVE * 1000))
|
||||
timeout_ms = (CURL_TIMEOUT_RESOLVE * 1000) - elapsed_ms;
|
||||
else
|
||||
timeout_ms = -1;
|
||||
}
|
||||
|
||||
max_timeout.tv_sec = itimeout_ms / 1000;
|
||||
max_timeout.tv_usec = (itimeout_ms % 1000) * 1000;
|
||||
if(timeout_ms < 0) {
|
||||
result = CURLE_OPERATION_TIMEDOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
real_timeout = ares_timeout(ares->channel, &max_timeout, &time_buf);
|
||||
|
||||
/* use the timeout period ares returned to us above if less than one
|
||||
second is left, otherwise use 1000ms to make sure the progress callback
|
||||
gets called frequent enough */
|
||||
if(!real_timeout->tv_sec)
|
||||
call_timeout_ms = (timediff_t)(real_timeout->tv_usec / 1000);
|
||||
else
|
||||
call_timeout_ms = 1000;
|
||||
|
||||
if(Curl_ares_perform(ares->channel, call_timeout_ms) < 0)
|
||||
return CURLE_UNRECOVERABLE_POLL;
|
||||
if(Curl_ares_perform(ares->channel,
|
||||
async_ares_poll_timeout(ares, timeout_ms)) < 0) {
|
||||
result = CURLE_UNRECOVERABLE_POLL;
|
||||
break;
|
||||
}
|
||||
|
||||
result = Curl_async_is_resolved(data, dns);
|
||||
if(result || data->state.async.done)
|
||||
break;
|
||||
|
||||
if(Curl_pgrsUpdate(data))
|
||||
if(Curl_pgrsUpdate(data)) {
|
||||
result = CURLE_ABORTED_BY_CALLBACK;
|
||||
else {
|
||||
struct curltime now = curlx_now(); /* update in loop */
|
||||
timediff_t elapsed_ms = curlx_ptimediff_ms(&now, Curl_pgrs_now(data));
|
||||
if(elapsed_ms <= 0)
|
||||
timeout_ms -= 1; /* always deduct at least 1 */
|
||||
else if(elapsed_ms > timeout_ms)
|
||||
timeout_ms = -1;
|
||||
else
|
||||
timeout_ms -= elapsed_ms;
|
||||
break;
|
||||
}
|
||||
if(timeout_ms < 0)
|
||||
result = CURLE_OPERATION_TIMEDOUT;
|
||||
}
|
||||
|
||||
/* Operation complete, if the lookup was successful we now have the entry
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue