diff --git a/CHANGES b/CHANGES index fbd6bf4267..668eb23180 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +4094. [bug] A race during shutdown or reconfiguration could + cause an assertion in mem.c. [RT #38979] + 4093. [func] Dig now learns the SIT value from truncated responses when it retries over TCP. [RT #39047] diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml index 624e9d417f..9294996e35 100644 --- a/doc/arm/notes.xml +++ b/doc/arm/notes.xml @@ -581,6 +581,12 @@ in zt.c. [RT #37573] + + + A race during shutdown or reconfiguration could + cause an assertion failure in mem.c. [RT #38979] + + diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index e8e51155c5..aaa58846a5 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -533,6 +533,8 @@ static void add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, static inline isc_result_t findnoqname(fetchctx_t *fctx, dns_name_t *name, dns_rdatatype_t type, dns_name_t **noqname); +static void fctx_increference(fetchctx_t *fctx); +static isc_boolean_t fctx_decreference(fetchctx_t *fctx); /*% * Increment resolver-related statistics counters. @@ -815,10 +817,12 @@ fctx_startidletimer(fetchctx_t *fctx, isc_interval_t *interval) { */ #define fctx_stopidletimer fctx_starttimer - static inline void resquery_destroy(resquery_t **queryp) { + dns_resolver_t *res; + isc_boolean_t empty; resquery_t *query; + fetchctx_t *fctx; REQUIRE(queryp != NULL); query = *queryp; @@ -826,15 +830,21 @@ resquery_destroy(resquery_t **queryp) { INSIST(query->tcpsocket == NULL); - query->fctx->nqueries--; - if (SHUTTINGDOWN(query->fctx)) { - dns_resolver_t *res = query->fctx->res; - if (maybe_destroy(query->fctx, ISC_FALSE)) - empty_bucket(res); - } + fctx = query->fctx; + res = fctx->res; + + fctx->nqueries--; + + LOCK(&res->buckets[fctx->bucketnum].lock); + empty = fctx_decreference(query->fctx); + UNLOCK(&res->buckets[fctx->bucketnum].lock); + query->magic = 0; isc_mem_put(query->mctx, query, sizeof(*query)); *queryp = NULL; + + if (empty) + empty_bucket(res); } static void @@ -1621,6 +1631,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, } query->dispentry = NULL; + fctx_increference(fctx); query->fctx = fctx; query->tsig = NULL; query->tsigkey = NULL; @@ -6970,10 +6981,21 @@ answer_response(fetchctx_t *fctx) { return (result); } +static void +fctx_increference(fetchctx_t *fctx) { + REQUIRE(VALID_FCTX(fctx)); + + LOCK(&fctx->res->buckets[fctx->bucketnum].lock); + fctx->references++; + UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock); +} + static isc_boolean_t fctx_decreference(fetchctx_t *fctx) { isc_boolean_t bucket_empty = ISC_FALSE; + REQUIRE(VALID_FCTX(fctx)); + INSIST(fctx->references > 0); fctx->references--; if (fctx->references == 0) { @@ -8209,9 +8231,7 @@ resquery_response(isc_task_t *task, isc_event_t *event) { if (result != ISC_R_SUCCESS) fctx_done(fctx, result, __LINE__); else { - LOCK(&fctx->res->buckets[fctx->bucketnum].lock); - fctx->references++; - UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock); + fctx_increference(fctx); result = fctx_stopidletimer(fctx); if (result != ISC_R_SUCCESS) fctx_done(fctx, result, __LINE__);