evdns: fix EVDNS_BASE_DISABLE_WHEN_INACTIVE in case retransmit/retry

This commit is contained in:
Azat Khuzhin 2014-04-10 19:30:47 +04:00
parent 07b5e45ba5
commit 74d0eee89b

20
evdns.c
View File

@ -541,6 +541,17 @@ nameserver_probe_failed(struct nameserver *const ns) {
} }
} }
static void
request_swap_ns(struct request *req, struct nameserver *ns) {
if (ns && req->ns != ns) {
EVUTIL_ASSERT(req->ns->requests_inflight > 0);
req->ns->requests_inflight--;
ns->requests_inflight++;
req->ns = ns;
}
}
/* called when a nameserver has been deemed to have failed. For example, too */ /* called when a nameserver has been deemed to have failed. For example, too */
/* many packets have timed out etc */ /* many packets have timed out etc */
static void static void
@ -595,7 +606,7 @@ nameserver_failed(struct nameserver *const ns, const char *msg) {
if (req->tx_count == 0 && req->ns == ns) { if (req->tx_count == 0 && req->ns == ns) {
/* still waiting to go out, can be moved */ /* still waiting to go out, can be moved */
/* to another server */ /* to another server */
req->ns = nameserver_pick(base); request_swap_ns(req, nameserver_pick(base));
} }
req = req->next; req = req->next;
} while (req != started_at); } while (req != started_at);
@ -708,7 +719,7 @@ request_reissue(struct request *req) {
/* the last nameserver should have been marked as failing */ /* the last nameserver should have been marked as failing */
/* by the caller of this function, therefore pick will try */ /* by the caller of this function, therefore pick will try */
/* not to return it */ /* not to return it */
req->ns = nameserver_pick(req->base); request_swap_ns(req, nameserver_pick(req->base));
if (req->ns == last_ns) { if (req->ns == last_ns) {
/* ... but pick did return it */ /* ... but pick did return it */
/* not a lot of point in trying again with the */ /* not a lot of point in trying again with the */
@ -2173,13 +2184,10 @@ evdns_request_timeout_callback(evutil_socket_t fd, short events, void *arg) {
request_finished(req, &REQ_HEAD(req->base, req->trans_id), 1); request_finished(req, &REQ_HEAD(req->base, req->trans_id), 1);
} else { } else {
/* retransmit it */ /* retransmit it */
struct nameserver *new_ns;
log(EVDNS_LOG_DEBUG, "Retransmitting request %p; tx_count==%d", log(EVDNS_LOG_DEBUG, "Retransmitting request %p; tx_count==%d",
arg, req->tx_count); arg, req->tx_count);
(void) evtimer_del(&req->timeout_event); (void) evtimer_del(&req->timeout_event);
new_ns = nameserver_pick(base); request_swap_ns(req, nameserver_pick(base));
if (new_ns)
req->ns = new_ns;
evdns_request_transmit(req); evdns_request_transmit(req);
} }
EVDNS_UNLOCK(base); EVDNS_UNLOCK(base);