]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
2921. [bug] The resolver could attempt to destroy a fetch context
authorMark Andrews <marka@isc.org>
Wed, 23 Jun 2010 01:50:23 +0000 (01:50 +0000)
committerMark Andrews <marka@isc.org>
Wed, 23 Jun 2010 01:50:23 +0000 (01:50 +0000)
                        to soon.  [RT #19878]

CHANGES
lib/dns/resolver.c

diff --git a/CHANGES b/CHANGES
index c423c080ada305ef0a330e2815e5c489188d3e38..ba7d283a7af6ee1b61ee4de8cb4b8f17887f8098 100644 (file)
--- 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.
index 6d2fbed1a2bcde5ba6b10f73cd33320360645611..f84eede9084abcbe168ea01d613f5a1bdc6826fa 100644 (file)
@@ -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);