Merge pull request #174 from azat/dns-fail-disable-when-inactive-fix-v3

Dns fail disable when inactive fix v3
This commit is contained in:
Nick Mathewson 2014-10-09 11:48:38 -04:00
commit c750c704c1
2 changed files with 49 additions and 16 deletions

33
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 */
/* many packets have timed out etc */
static void
@ -595,7 +606,7 @@ nameserver_failed(struct nameserver *const ns, const char *msg) {
if (req->tx_count == 0 && req->ns == ns) {
/* still waiting to go out, can be moved */
/* to another server */
req->ns = nameserver_pick(base);
request_swap_ns(req, nameserver_pick(base));
}
req = req->next;
} while (req != started_at);
@ -708,7 +719,7 @@ request_reissue(struct request *req) {
/* the last nameserver should have been marked as failing */
/* by the caller of this function, therefore pick will try */
/* not to return it */
req->ns = nameserver_pick(req->base);
request_swap_ns(req, nameserver_pick(req->base));
if (req->ns == last_ns) {
/* ... but pick did return it */
/* not a lot of point in trying again with the */
@ -2159,12 +2170,6 @@ evdns_request_timeout_callback(evutil_socket_t fd, short events, void *arg) {
log(EVDNS_LOG_DEBUG, "Request %p timed out", arg);
EVDNS_LOCK(base);
req->ns->timedout++;
if (req->ns->timedout > req->base->global_max_nameserver_timeout) {
req->ns->timedout = 0;
nameserver_failed(req->ns, "request timed out.");
}
if (req->tx_count >= req->base->global_max_retransmits) {
/* this request has failed */
log(EVDNS_LOG_DEBUG, "Giving up on request %p; tx_count==%d",
@ -2173,15 +2178,19 @@ evdns_request_timeout_callback(evutil_socket_t fd, short events, void *arg) {
request_finished(req, &REQ_HEAD(req->base, req->trans_id), 1);
} else {
/* retransmit it */
struct nameserver *new_ns;
log(EVDNS_LOG_DEBUG, "Retransmitting request %p; tx_count==%d",
arg, req->tx_count);
(void) evtimer_del(&req->timeout_event);
new_ns = nameserver_pick(base);
if (new_ns)
req->ns = new_ns;
request_swap_ns(req, nameserver_pick(base));
evdns_request_transmit(req);
}
req->ns->timedout++;
if (req->ns->timedout > req->base->global_max_nameserver_timeout) {
req->ns->timedout = 0;
nameserver_failed(req->ns, "request timed out.");
}
EVDNS_UNLOCK(base);
}

View File

@ -671,7 +671,7 @@ end:
}
static void
dns_retry_test(void *arg)
dns_retry_test_impl(void *arg, int flags)
{
struct basic_test_data *data = arg;
struct event_base *base = data->base;
@ -688,7 +688,7 @@ dns_retry_test(void *arg)
tt_assert(port);
evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum);
dns = evdns_base_new(base, 0);
dns = evdns_base_new(base, flags);
tt_assert(!evdns_base_nameserver_ip_add(dns, buf));
tt_assert(! evdns_base_set_option(dns, "timeout", "0.2"));
tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "10"));
@ -743,6 +743,16 @@ end:
if (port)
evdns_close_server_port(port);
}
static void
dns_retry_test(void *arg)
{
dns_retry_test_impl(arg, 0);
}
static void
dns_retry_disable_when_inactive_test(void *arg)
{
dns_retry_test_impl(arg, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
}
static struct regress_dns_server_table internal_error_table[] = {
/* Error 4 (NOTIMPL) makes us reissue the request to another server
@ -760,7 +770,7 @@ static struct regress_dns_server_table reissue_table[] = {
};
static void
dns_reissue_test(void *arg)
dns_reissue_test_impl(void *arg, int flags)
{
struct basic_test_data *data = arg;
struct event_base *base = data->base;
@ -779,7 +789,7 @@ dns_reissue_test(void *arg)
evutil_snprintf(buf1, sizeof(buf1), "127.0.0.1:%d", (int)portnum1);
evutil_snprintf(buf2, sizeof(buf2), "127.0.0.1:%d", (int)portnum2);
dns = evdns_base_new(base, 0);
dns = evdns_base_new(base, flags);
tt_assert(!evdns_base_nameserver_ip_add(dns, buf1));
tt_assert(! evdns_base_set_option(dns, "timeout:", "0.3"));
tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "2"));
@ -812,6 +822,16 @@ end:
if (port2)
evdns_close_server_port(port2);
}
static void
dns_reissue_test(void *arg)
{
dns_reissue_test_impl(arg, 0);
}
static void
dns_reissue_disable_when_inactive_test(void *arg)
{
dns_reissue_test_impl(arg, EVDNS_BASE_DISABLE_WHEN_INACTIVE);
}
#if 0
static void
@ -1971,7 +1991,11 @@ struct testcase_t dns_testcases[] = {
{ "search_cancel", dns_search_cancel_test,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
{ "retry", dns_retry_test, TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
{ "retry_disable_when_inactive", dns_retry_disable_when_inactive_test,
TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
{ "reissue", dns_reissue_test, TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
{ "reissue_disable_when_inactive", dns_reissue_disable_when_inactive_test,
TT_FORK|TT_NEED_BASE|TT_NO_LOGS, &basic_setup, NULL },
{ "inflight", dns_inflight_test, TT_FORK|TT_NEED_BASE, &basic_setup, NULL },
{ "bufferevent_connect_hostname", test_bufferevent_connect_hostname,
TT_FORK|TT_NEED_BASE, &basic_setup, NULL },