From: Mark Andrews Date: Wed, 23 Jun 2010 01:50:23 +0000 (+0000) Subject: 2921. [bug] The resolver could attempt to destroy a fetch context X-Git-Tag: v9.5.3b1~43 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6dadf18f4d5b26eace314d18fd25f7234c68acdf;p=thirdparty%2Fbind9.git 2921. [bug] The resolver could attempt to destroy a fetch context to soon. [RT #19878] --- diff --git a/CHANGES b/CHANGES index c423c080ada..ba7d283a7af 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +2921. [bug] The resolver could attempt to destroy a fetch context + to soon. [RT #19878] + 2918. [maint] Add AAAA address for I.ROOT-SERVERS.NET. 2916. [func] Add framework to use IPv6 in tests. diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 6d2fbed1a2b..f84eede9084 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.c,v 1.355.12.54 2010/04/20 23:47:12 tbox Exp $ */ +/* $Id: resolver.c,v 1.355.12.55 2010/06/23 01:50:23 marka Exp $ */ /*! \file */ @@ -5760,13 +5760,40 @@ answer_response(fetchctx_t *fctx) { return (result); } +static isc_boolean_t +fctx_decreference(fetchctx_t *fctx) { + isc_boolean_t bucket_empty = ISC_FALSE; + + INSIST(fctx->references > 0); + fctx->references--; + if (fctx->references == 0) { + /* + * No one cares about the result of this fetch anymore. + */ + if (fctx->pending == 0 && fctx->nqueries == 0 && + ISC_LIST_EMPTY(fctx->validators) && SHUTTINGDOWN(fctx)) { + /* + * This fctx is already shutdown; we were just + * waiting for the last reference to go away. + */ + bucket_empty = fctx_destroy(fctx); + } else { + /* + * Initiate shutdown. + */ + fctx_shutdown(fctx); + } + } + return (bucket_empty); +} + static void resume_dslookup(isc_task_t *task, isc_event_t *event) { dns_fetchevent_t *fevent; dns_resolver_t *res; fetchctx_t *fctx; isc_result_t result; - isc_boolean_t bucket_empty = ISC_FALSE; + isc_boolean_t bucket_empty; isc_boolean_t locked = ISC_FALSE; unsigned int bucketnum; dns_rdataset_t nameservers; @@ -5870,9 +5897,7 @@ resume_dslookup(isc_task_t *task, isc_event_t *event) { isc_event_free(&event); if (!locked) LOCK(&res->buckets[bucketnum].lock); - fctx->references--; - if (fctx->references == 0) - bucket_empty = fctx_destroy(fctx); + bucket_empty = fctx_decreference(fctx); UNLOCK(&res->buckets[bucketnum].lock); if (bucket_empty) empty_bucket(res); @@ -6719,12 +6744,14 @@ resquery_response(isc_task_t *task, isc_event_t *event) { &fctx->nsfetch); if (result != ISC_R_SUCCESS) fctx_done(fctx, result, __LINE__); - LOCK(&fctx->res->buckets[fctx->bucketnum].lock); - fctx->references++; - UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock); - result = fctx_stopidletimer(fctx); - 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); + result = fctx_stopidletimer(fctx); + if (result != ISC_R_SUCCESS) + fctx_done(fctx, result, __LINE__); + } } else { /* * We're done. @@ -7569,7 +7596,7 @@ dns_resolver_destroyfetch(dns_fetch_t **fetchp) { dns_fetchevent_t *event, *next_event; fetchctx_t *fctx; unsigned int bucketnum; - isc_boolean_t bucket_empty = ISC_FALSE; + isc_boolean_t bucket_empty; REQUIRE(fetchp != NULL); fetch = *fetchp; @@ -7597,27 +7624,7 @@ dns_resolver_destroyfetch(dns_fetch_t **fetchp) { } } - INSIST(fctx->references > 0); - fctx->references--; - if (fctx->references == 0) { - /* - * No one cares about the result of this fetch anymore. - */ - if (fctx->pending == 0 && fctx->nqueries == 0 && - ISC_LIST_EMPTY(fctx->validators) && - SHUTTINGDOWN(fctx)) { - /* - * This fctx is already shutdown; we were just - * waiting for the last reference to go away. - */ - bucket_empty = fctx_destroy(fctx); - } else { - /* - * Initiate shutdown. - */ - fctx_shutdown(fctx); - } - } + bucket_empty = fctx_decreference(fctx); UNLOCK(&res->buckets[bucketnum].lock);