diff --git a/CHANGES b/CHANGES index 8989fe597b..b4e0b5fd13 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +1111. [bug] Multithreaded servers could deadlock processing + recursive queries due to a locking hieararchy + violation in adb.c. [RT #2017] + 1110. [bug] dig only accept valid abbreviations of +options. [RT #2003] diff --git a/lib/dns/adb.c b/lib/dns/adb.c index 0284629805..6e4c46c31c 100644 --- a/lib/dns/adb.c +++ b/lib/dns/adb.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: adb.c,v 1.189 2001/11/07 04:25:15 marka Exp $ */ +/* $Id: adb.c,v 1.190 2001/11/07 22:40:33 gson Exp $ */ /* * Implementation notes @@ -115,7 +115,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; @@ -302,7 +302,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); @@ -1184,18 +1184,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) { @@ -1215,7 +1213,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); @@ -1226,34 +1224,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); - adb->erefcnt--; - if (adb->erefcnt == 0) + LOCK(&adb->reflock); + adb->erefcnt--; + zeroerefcnt = ISC_TF(adb->erefcnt == 0); + UNLOCK(&adb->reflock); + + if (zeroerefcnt) check_exit(adb); if (lock) @@ -2164,7 +2164,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); @@ -2234,7 +2234,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; @@ -2343,7 +2343,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: @@ -2360,7 +2360,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; } @@ -2398,12 +2398,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) {