-
Notifications
You must be signed in to change notification settings - Fork 643
Description
c-ares/src/lib/ares__threads.c
Lines 571 to 589 in fd81f36
| while (ares__llist_len(channel->all_queries)) { | |
| if (timeout_ms < 0) { | |
| ares__thread_cond_wait(channel->cond_empty, channel->lock); | |
| } else { | |
| struct timeval tv_remaining; | |
| struct timeval tv_now = ares__tvnow(); | |
| unsigned long tms; | |
| ares__timeval_remaining(&tv_remaining, &tv_now, &tout); | |
| tms = (unsigned long)((tv_remaining.tv_sec * 1000) + | |
| (tv_remaining.tv_usec / 1000)); | |
| if (tms == 0) { | |
| status = ARES_ETIMEOUT; | |
| } else { | |
| status = | |
| ares__thread_cond_timedwait(channel->cond_empty, channel->lock, tms); | |
| } | |
| } | |
| } |
There's nothing to cancel or timeout or server the pending requests and break out of the loop in the tms == 0 case. If the timeout is short enough that it expires while, e.g., waiting to obtain the mutex, then while the status is set to ARES_ETIMEOUT, the mutex isn't released (unlike the other branches which call ares__thread_cond_timedwait, which releases the mutex while waiting), and so the event thread when calling ares_process_fd cannot obtain the channel lock, channel->all_queries never decreases and the while loop never exits.
I believe the intention is to simply return ARES_ETIMEOUT and let the caller decide to perhaps call ares_cancel, though I'm not sure.