From 88f5f3915b557eef68864df4c80eee8750208108 Mon Sep 17 00:00:00 2001 From: Evan Hunt Date: Thu, 5 Nov 2020 14:15:14 -0800 Subject: [PATCH] dig: prevent query from being detached if udpconnect fails on first attempt FreeBSD sometimes returns spurious errors in UDP connect() attempts, so we try a few times before giving up. However, each failed attempt triggers a call to udp_ready() in dighost.c, and that was causing the query object to be detached prematurely. --- bin/dig/dighost.c | 10 ++++++---- bin/dig/dighost.h | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 081518cb17..d7b04c02ea 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -2897,7 +2897,9 @@ udp_ready(isc_nmhandle_t *handle, isc_result_t eresult, void *arg) { debug("udp setup failed: %s", isc_result_totext(eresult)); } - query_detach(&query); + if (query->tries == 0) { + query_detach(&query); + } return; } @@ -2933,7 +2935,6 @@ static void start_udp(dig_query_t *query) { isc_result_t result; dig_query_t *next = NULL; - int i = 0; REQUIRE(DIG_VALID_QUERY(query)); @@ -2985,6 +2986,7 @@ start_udp(dig_query_t *query) { } } + query->tries = 3; do { int local_timeout = timeout * 1000; if (local_timeout == 0) { @@ -2996,11 +2998,11 @@ start_udp(dig_query_t *query) { * in a spurious transient EADDRINUSE. Try a few more times * before giving up. */ - debug("isc_nm_udpconnect(): try %d", i + 1); + debug("isc_nm_udpconnect(): %d tries left", --query->tries); result = isc_nm_udpconnect(netmgr, (isc_nmiface_t *)&localaddr, (isc_nmiface_t *)&query->sockaddr, udp_ready, query, local_timeout, 0); - } while (result != ISC_R_SUCCESS && i++ < 2); + } while (result != ISC_R_SUCCESS && query->tries > 0); check_result(result, "isc_nm_udpconnect"); } diff --git a/bin/dig/dighost.h b/bin/dig/dighost.h index 6a30b5ef85..81cc2750a1 100644 --- a/bin/dig/dighost.h +++ b/bin/dig/dighost.h @@ -199,6 +199,7 @@ struct dig_query { isc_time_t time_recv; uint64_t byte_count; isc_timer_t *timer; + uint8_t tries; }; struct dig_server {