]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
pullup:
authorMark Andrews <marka@isc.org>
Mon, 12 Nov 2001 22:28:30 +0000 (22:28 +0000)
committerMark Andrews <marka@isc.org>
Mon, 12 Nov 2001 22:28:30 +0000 (22:28 +0000)
1111.   [bug]           Multithreaded servers could deadlock processing
                        recursive queries due to a locking hieararchy
                        violation in adb.c. [RT #2017]

CHANGES
lib/dns/adb.c

diff --git a/CHANGES b/CHANGES
index 8c043dcedd5a5a16df181bd0f8aff3468215fe34..ec1ebfd2816e9380d47ac12e7a753f75acbad0e1 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -5,6 +5,10 @@
 
 1114.  [port]          Ignore more accept() errors. [RT #2021]
 
+1111.  [bug]           Multithreaded servers could deadlock processing
+                       recursive queries due to a locking hieararchy
+                       violation in adb.c. [RT #2017]
+
 
        --- 9.2.0rc9 released ---
 
index 98c2b36f5332d4197407d06c498ae817f362438c..b90d86a01c41e46300b862905bc48f6c3dcd6c79 100644 (file)
@@ -15,7 +15,7 @@
  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: adb.c,v 1.181 2001/08/08 22:54:36 gson Exp $ */
+/* $Id: adb.c,v 1.181.2.1 2001/11/12 22:28:30 marka Exp $ */
 
 /*
  * Implementation notes
@@ -113,7 +113,7 @@ struct dns_adb {
        unsigned int                    magic;
 
        isc_mutex_t                     lock;
-       isc_mutex_t                     ilock;
+       isc_mutex_t                     reflock; /* Covers irefcnt, erefcnt */
        isc_mem_t                      *mctx;
        dns_view_t                     *view;
        isc_timermgr_t                 *timermgr;
@@ -299,7 +299,7 @@ static void print_namehook_list(FILE *, const char *legend,
 static void print_find_list(FILE *, dns_adbname_t *);
 static void print_fetch_list(FILE *, dns_adbname_t *);
 static inline void dec_adb_irefcnt(dns_adb_t *);
-static inline void inc_adb_erefcnt(dns_adb_t *, isc_boolean_t);
+static inline void inc_adb_erefcnt(dns_adb_t *);
 static inline void dec_adb_erefcnt(dns_adb_t *, isc_boolean_t);
 static inline void inc_entry_refcnt(dns_adb_t *, dns_adbentry_t *,
                                    isc_boolean_t);
@@ -1165,18 +1165,16 @@ static inline void
 check_exit(dns_adb_t *adb) {
        isc_event_t *event;
        isc_task_t *etask;
-       isc_boolean_t zeroirefcnt;
+       isc_boolean_t zeroirefcnt, zeroerefcnt;
 
        /*
         * The caller must be holding the adb lock.
         */
 
-       LOCK(&adb->ilock);
-       if (adb->irefcnt == 0)
-               zeroirefcnt = ISC_TRUE;
-       else
-               zeroirefcnt = ISC_FALSE;
-       UNLOCK(&adb->ilock);
+       LOCK(&adb->reflock);
+       zeroirefcnt = ISC_TF(adb->irefcnt == 0);
+       zeroerefcnt = ISC_TF(adb->erefcnt == 0);
+       UNLOCK(&adb->reflock);
 
        if (adb->shutting_down && zeroirefcnt &&
            isc_mempool_getallocated(adb->ahmp) == 0) {
@@ -1196,7 +1194,7 @@ check_exit(dns_adb_t *adb) {
                 * If there aren't any external references either, we're
                 * done.  Send the control event to initiate shutdown.
                 */
-               if (adb->erefcnt == 0) {
+               if (zeroerefcnt) {
                        INSIST(!adb->cevent_sent);      /* Sanity check. */
                        event = &adb->cevent;
                        isc_task_send(adb->task, &event);
@@ -1207,34 +1205,36 @@ check_exit(dns_adb_t *adb) {
 
 static inline void
 dec_adb_irefcnt(dns_adb_t *adb) {
-       LOCK(&adb->ilock);
+       LOCK(&adb->reflock);
 
        INSIST(adb->irefcnt > 0);
        adb->irefcnt--;
 
-       UNLOCK(&adb->ilock);
+       UNLOCK(&adb->reflock);
 }
 
 static inline void
-inc_adb_erefcnt(dns_adb_t *adb, isc_boolean_t lock) {
-       if (lock)
-               LOCK(&adb->lock);
-
+inc_adb_erefcnt(dns_adb_t *adb) {
+       LOCK(&adb->reflock);
        adb->erefcnt++;
-
-       if (lock)
-               UNLOCK(&adb->lock);
+       UNLOCK(&adb->reflock);
 }
 
 static inline void
 dec_adb_erefcnt(dns_adb_t *adb, isc_boolean_t lock) {
+       isc_boolean_t zeroerefcnt;
+
        if (lock)
                LOCK(&adb->lock);
 
        INSIST(adb->erefcnt > 0);
+
+       LOCK(&adb->reflock);
        adb->erefcnt--;
+       zeroerefcnt = ISC_TF(adb->erefcnt == 0);
+       UNLOCK(&adb->reflock);
 
-       if (adb->erefcnt == 0)
+       if (zeroerefcnt)
                check_exit(adb);
 
        if (lock)
@@ -2131,7 +2131,7 @@ destroy(dns_adb_t *adb) {
        isc_mutexblock_destroy(adb->entrylocks, NBUCKETS);
        isc_mutexblock_destroy(adb->namelocks, NBUCKETS);
 
-       DESTROYLOCK(&adb->ilock);
+       DESTROYLOCK(&adb->reflock);
        DESTROYLOCK(&adb->lock);
        DESTROYLOCK(&adb->mplock);
 
@@ -2198,7 +2198,7 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
        if (result != ISC_R_SUCCESS)
                goto fail0c;
 
-       result = isc_mutex_init(&adb->ilock);
+       result = isc_mutex_init(&adb->reflock);
        if (result != ISC_R_SUCCESS)
                goto fail0d;
 
@@ -2308,7 +2308,7 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
        if (adb->af6mp != NULL)
                isc_mempool_destroy(&adb->af6mp);
 
-       DESTROYLOCK(&adb->ilock);
+       DESTROYLOCK(&adb->reflock);
  fail0d:
        DESTROYLOCK(&adb->mplock);
  fail0c:
@@ -2325,7 +2325,7 @@ dns_adb_attach(dns_adb_t *adb, dns_adb_t **adbx) {
        REQUIRE(DNS_ADB_VALID(adb));
        REQUIRE(adbx != NULL && *adbx == NULL);
 
-       inc_adb_erefcnt(adb, ISC_TRUE);
+       inc_adb_erefcnt(adb);
        *adbx = adb;
 }
 
@@ -2363,12 +2363,9 @@ dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp) {
 
        LOCK(&adb->lock);
 
-       LOCK(&adb->ilock);
-       if (adb->irefcnt == 0)
-               zeroirefcnt = ISC_TRUE;
-       else
-               zeroirefcnt = ISC_FALSE;
-       UNLOCK(&adb->ilock);
+       LOCK(&adb->reflock);
+       zeroirefcnt = ISC_TF(adb->irefcnt == 0);
+       UNLOCK(&adb->reflock);
 
        if (adb->shutting_down && zeroirefcnt &&
            isc_mempool_getallocated(adb->ahmp) == 0) {