]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
589. [bug] The server could deadlock if a zone was updated
authorAndreas Gustafsson <source@isc.org>
Mon, 4 Dec 2000 06:31:41 +0000 (06:31 +0000)
committerAndreas Gustafsson <source@isc.org>
Mon, 4 Dec 2000 06:31:41 +0000 (06:31 +0000)
                        while being transferred out.

CHANGES
bin/named/xfrout.c

diff --git a/CHANGES b/CHANGES
index e02aea0f10354914cc4233046043a70c64d52684..69183ea998d8982231452b004ea977cc9ea81d21 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+
+ 589.  [bug]           The server could deadlock if a zone was updated 
+                       while being transferred out.
+
  588.  [bug]           ctx->in_use was not being correctly initalised when
                        when pushing a file for $INCLUDE. [RT #523]
 
index b8e3b171f0c07c7c36e8637a58f80e8e4fff90dc..c2da755e1773a533c5042984977ab8e4b21fb7d7 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: xfrout.c,v 1.82 2000/11/17 19:04:51 gson Exp $ */
+/* $Id: xfrout.c,v 1.83 2000/12/04 06:31:41 gson Exp $ */
 
 #include <config.h>
 
@@ -223,6 +223,11 @@ db_rr_iterator_next(db_rr_iterator_t *it) {
        return (it->result);
 }
 
+static void
+db_rr_iterator_pause(db_rr_iterator_t *it) {
+       dns_dbiterator_pause(it->dbit);
+}
+
 static void
 db_rr_iterator_destroy(db_rr_iterator_t *it) {
        if (dns_rdataset_isassociated(&it->rdataset))
@@ -316,9 +321,15 @@ struct rrstream_methods {
                                           dns_name_t **,
                                           isc_uint32_t *,
                                           dns_rdata_t **);
+       void                    (*pause)(rrstream_t *);
        void                    (*destroy)(rrstream_t **);
 };
 
+static void
+rrstream_noop_pause(rrstream_t *rs) {
+       UNUSED(rs);
+}
+
 /**************************************************************************/
 /*
  * An 'ixfr_rrstream_t' is an 'rrstream_t' that returns
@@ -410,12 +421,13 @@ static rrstream_methods_t ixfr_rrstream_methods = {
        ixfr_rrstream_first,
        ixfr_rrstream_next,
        ixfr_rrstream_current,
+       rrstream_noop_pause,
        ixfr_rrstream_destroy
 };
 
 /**************************************************************************/
 /*
- * An 'ixfr_rrstream_t' is an 'rrstream_t' that returns
+ * An 'axfr_rrstream_t' is an 'rrstream_t' that returns
  * an AXFR-like RR stream from a database.
  *
  * The SOAs at the beginning and end of the transfer are
@@ -425,7 +437,7 @@ static rrstream_methods_t ixfr_rrstream_methods = {
 typedef struct axfr_rrstream {
        rrstream_t              common;
        int                     state;
-       db_rr_iterator_t                it;
+       db_rr_iterator_t        it;
        isc_boolean_t           it_valid;
 } axfr_rrstream_t;
 
@@ -516,6 +528,12 @@ axfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
        db_rr_iterator_current(&s->it, name, ttl, rdata);
 }
 
+static void
+axfr_rrstream_pause(rrstream_t *rs) {
+       axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
+       db_rr_iterator_pause(&s->it);
+}
+
 static void
 axfr_rrstream_destroy(rrstream_t **rsp) {
        axfr_rrstream_t *s = (axfr_rrstream_t *) *rsp;
@@ -528,6 +546,7 @@ static rrstream_methods_t axfr_rrstream_methods = {
        axfr_rrstream_first,
        axfr_rrstream_next,
        axfr_rrstream_current,
+       axfr_rrstream_pause,
        axfr_rrstream_destroy
 };
 
@@ -611,6 +630,7 @@ static rrstream_methods_t soa_rrstream_methods = {
        soa_rrstream_first,
        soa_rrstream_next,
        soa_rrstream_current,
+       rrstream_noop_pause,
        soa_rrstream_destroy
 };
 
@@ -698,6 +718,11 @@ compound_rrstream_next(rrstream_t *rs) {
        rrstream_t *curstream = s->components[s->state];
        s->result = curstream->methods->next(curstream);
        while (s->result == ISC_R_NOMORE) {
+               /*
+                * Make sure locks held by the current stream
+                * are released before we switch streams.
+                */
+               curstream->methods->pause(curstream);
                if (s->state == 2)
                        return (ISC_R_NOMORE);
                s->state++;
@@ -719,6 +744,16 @@ compound_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
        curstream->methods->current(curstream, name, ttl, rdata);
 }
 
+static void
+compound_rrstream_pause(rrstream_t *rs)
+{
+       compound_rrstream_t *s = (compound_rrstream_t *) rs;
+       rrstream_t *curstream;
+       INSIST(0 <= s->state && s->state < 3);
+       curstream = s->components[s->state];
+       curstream->methods->pause(curstream);
+}
+
 static void
 compound_rrstream_destroy(rrstream_t **rsp) {
        compound_rrstream_t *s = (compound_rrstream_t *) *rsp;
@@ -732,6 +767,7 @@ static rrstream_methods_t compound_rrstream_methods = {
        compound_rrstream_first,
        compound_rrstream_next,
        compound_rrstream_current,
+       compound_rrstream_pause,
        compound_rrstream_destroy
 };
 
@@ -1411,7 +1447,8 @@ sendstream(xfrout_ctx_t *xfr) {
                msg = NULL;
                ns_client_send(xfr->client);
                xfrout_ctx_destroy(&xfr);
-               return;
+               result = ISC_R_SUCCESS;
+               goto done;
        }
 
        /* Advance lasttsig to be the last TSIG generated */
@@ -1440,6 +1477,14 @@ sendstream(xfrout_ctx_t *xfr) {
                }
                dns_message_destroy(&msg);
        }
+
+ done:
+       /*
+        * Make sure to release any locks held by database
+        * iterators before returning from the event handler.
+        */
+       xfr->stream->methods->pause(xfr->stream);
+       
        if (result == ISC_R_SUCCESS)
                return;