]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
[master] hold a reference on fetch context during query
authorEvan Hunt <each@isc.org>
Wed, 8 Apr 2015 21:33:45 +0000 (14:33 -0700)
committerEvan Hunt <each@isc.org>
Wed, 8 Apr 2015 21:33:45 +0000 (14:33 -0700)
4094. [bug] A race during shutdown or reconfiguration could
cause an assertion in mem.c. [RT #38979]

CHANGES
doc/arm/notes.xml
lib/dns/resolver.c

diff --git a/CHANGES b/CHANGES
index fbd6bf4267daaa8a5b57ecc1726e5e0aa21747f6..668eb23180f390b4e5639494b25108e5679db88c 100644 (file)
--- 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]
 
index 624e9d417fac934b8298515c277f608f124b0f8d..9294996e35306a84684d460a7a321e05dc70b4cc 100644 (file)
          in zt.c. [RT #37573]
        </para>
       </listitem>
+      <listitem>
+       <para>
+         A race during shutdown or reconfiguration could
+         cause an assertion failure in mem.c. [RT #38979]
+       </para>
+      </listitem>
     </itemizedlist>
   </sect2>
   <sect2 id="end_of_life">
index e8e51155c5d807e52517655528b68af89621f4ac..aaa58846a52b3b8df625a53779b8ed42647a9db3 100644 (file)
@@ -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__);