async-ares: blocking resolve timeout handling, better
No binary (build failed)
—
(log yok)
| @@ -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; |
| - | |
| - | #if TIMEDIFF_T_MAX > INT_MAX |
| - | itimeout_ms = (timeout_ms > INT_MAX) ? INT_MAX : (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; |
| + | timediff_t timeout_ms; |
| - | real_timeout = ares_timeout(ares->channel, &max_timeout, &time_buf); |
| + | 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; |
| + | } |
| - | /* 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(timeout_ms < 0) { |
| + | result = CURLE_OPERATION_TIMEDOUT; |
| + | break; |
| + | } |
| - | 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 | |