diff --git a/doc/private/branches b/doc/private/branches index fc66a25262..962faba557 100644 --- a/doc/private/branches +++ b/doc/private/branches @@ -4,16 +4,7 @@ a6_remove open jinmei blabel-cleanup ipv6_6to4 feedback marka libbind_clean open jinmei -rt3598 closed explorer -rt3625 closed explorer rt3746 open marka -rt3892 closed explorer -rt4090 closed explorer -rt4112 closed explorer -adb_race review explorer -rt4319 closed explorer -rt3907 closed explorer -rt3507 closed ogud (pull down by explorer) v6source rt3445 closed @@ -26,3 +17,12 @@ rt3502 closed ipv6-improvements closed ipv6-scope closed marka_google closed +rt3598 closed explorer +rt3625 closed explorer +rt3892 closed explorer +rt4090 closed explorer +rt4112 closed explorer +rt4319 closed explorer +rt3907 closed explorer +rt3507 closed ogud (pull down by explorer) +adb_race closed explorer diff --git a/lib/dns/adb.c b/lib/dns/adb.c index 5f6d44099e..5d04d7b7c6 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.198 2002/09/12 00:28:52 marka Exp $ */ +/* $Id: adb.c,v 1.199 2002/11/13 00:07:04 explorer Exp $ */ /* * Implementation notes @@ -282,7 +282,7 @@ static inline void free_adbzoneinfo(dns_adb_t *, dns_adbzoneinfo_t **); static inline dns_adbentry_t *new_adbentry(dns_adb_t *); static inline void free_adbentry(dns_adb_t *, dns_adbentry_t **); static inline dns_adbfind_t *new_adbfind(dns_adb_t *); -static inline void free_adbfind(dns_adb_t *, dns_adbfind_t **); +static inline isc_boolean_t free_adbfind(dns_adb_t *, dns_adbfind_t **); static inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *, dns_adbentry_t *, in_port_t); static inline dns_adbfetch_t *new_adbfetch(dns_adb_t *); @@ -302,18 +302,19 @@ static void print_namehook_list(FILE *, const char *legend, isc_stdtime_t now); 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 isc_boolean_t dec_adb_irefcnt(dns_adb_t *); +static inline void inc_adb_irefcnt(dns_adb_t *); static inline void inc_adb_erefcnt(dns_adb_t *); static inline void inc_entry_refcnt(dns_adb_t *, dns_adbentry_t *, isc_boolean_t); -static inline void dec_entry_refcnt(dns_adb_t *, dns_adbentry_t *, +static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, dns_adbentry_t *, isc_boolean_t); static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *); -static void clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *); +static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *); static void clean_target(dns_adb_t *, dns_name_t *); static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, unsigned int); -static void check_expire_namehooks(dns_adbname_t *, isc_stdtime_t, +static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t, isc_boolean_t); static void cancel_fetches_at_name(dns_adbname_t *); static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t, @@ -324,13 +325,13 @@ static isc_result_t fetch_name_a6(dns_adbname_t *, isc_boolean_t); static inline void check_exit(dns_adb_t *); static void timer_cleanup(isc_task_t *, isc_event_t *); static void destroy(dns_adb_t *); -static void shutdown_names(dns_adb_t *); -static void shutdown_entries(dns_adb_t *); +static isc_boolean_t shutdown_names(dns_adb_t *); +static isc_boolean_t shutdown_entries(dns_adb_t *); static inline void link_name(dns_adb_t *, int, dns_adbname_t *); -static inline void unlink_name(dns_adb_t *, dns_adbname_t *); +static inline isc_boolean_t unlink_name(dns_adb_t *, dns_adbname_t *); static inline void link_entry(dns_adb_t *, int, dns_adbentry_t *); -static inline void unlink_entry(dns_adb_t *, dns_adbentry_t *); -static void kill_name(dns_adbname_t **, isc_eventtype_t); +static inline isc_boolean_t unlink_entry(dns_adb_t *, dns_adbentry_t *); +static isc_boolean_t kill_name(dns_adbname_t **, isc_eventtype_t); static void fetch_callback_a6(isc_task_t *, isc_event_t *); static isc_result_t dbfind_a6(dns_adbname_t *, isc_stdtime_t); static void water(void *arg, int mark); @@ -677,9 +678,11 @@ import_a6(dns_a6context_t *a6ctx) { /* * Requires the name's bucket be locked. */ -static void +static isc_boolean_t kill_name(dns_adbname_t **n, isc_eventtype_t ev) { dns_adbname_t *name; + isc_boolean_t result = ISC_FALSE; + isc_boolean_t result4, result6; dns_adb_t *adb; INSIST(n != NULL); @@ -696,9 +699,11 @@ kill_name(dns_adbname_t **n, isc_eventtype_t ev) { * away now or not. */ if (NAME_DEAD(name) && !NAME_FETCH(name)) { - unlink_name(adb, name); + result = unlink_name(adb, name); free_adbname(adb, &name); - return; + if (result) + result = dec_adb_irefcnt(adb); + return (result); } /* @@ -706,32 +711,39 @@ kill_name(dns_adbname_t **n, isc_eventtype_t ev) { * in that they will always empty the list. */ clean_finds_at_name(name, ev, DNS_ADBFIND_ADDRESSMASK); - clean_namehooks(adb, &name->v4); - clean_namehooks(adb, &name->v6); + result4 = clean_namehooks(adb, &name->v4); + result6 = clean_namehooks(adb, &name->v6); clean_target(adb, &name->target); + result = ISC_TF(result4 || result6); /* * If fetches are running, cancel them. If none are running, we can * just kill the name here. */ if (!NAME_FETCH(name)) { - unlink_name(adb, name); + INSIST(result == ISC_FALSE); + result = unlink_name(adb, name); free_adbname(adb, &name); + if (result) + result = dec_adb_irefcnt(adb); } else { name->flags |= NAME_IS_DEAD; cancel_fetches_at_name(name); } + return (result); } /* * Requires the name's bucket be locked and no entry buckets be locked. */ -static void +static isc_boolean_t check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now, isc_boolean_t overmem) { dns_adb_t *adb; isc_boolean_t expire; + isc_boolean_t result4 = ISC_FALSE; + isc_boolean_t result6 = ISC_FALSE; INSIST(DNS_ADBNAME_VALID(name)); adb = name->adb; @@ -753,7 +765,7 @@ check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now, (expire || EXPIRE_OK(name->expire_v4, now))) { if (NAME_HAS_V4(name)) { DP(DEF_LEVEL, "expiring v4 for name %p", name); - clean_namehooks(adb, &name->v4); + result4 = clean_namehooks(adb, &name->v4); name->partial_result &= ~DNS_ADBFIND_INET; } name->expire_v4 = INT_MAX; @@ -766,7 +778,7 @@ check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now, (expire || EXPIRE_OK(name->expire_v6, now))) { if (NAME_HAS_V6(name)) { DP(DEF_LEVEL, "expiring v6 for name %p", name); - clean_namehooks(adb, &name->v6); + result6 = clean_namehooks(adb, &name->v6); name->partial_result &= ~DNS_ADBFIND_INET6; } name->expire_v6 = INT_MAX; @@ -779,6 +791,7 @@ check_expire_namehooks(dns_adbname_t *name, isc_stdtime_t now, clean_target(adb, &name->target); name->expire_target = INT_MAX; } + return (ISC_TF(result4 || result6)); } /* @@ -796,9 +809,10 @@ link_name(dns_adb_t *adb, int bucket, dns_adbname_t *name) { /* * Requires the name's bucket be locked. */ -static inline void +static inline isc_boolean_t unlink_name(dns_adb_t *adb, dns_adbname_t *name) { int bucket; + isc_boolean_t result = ISC_FALSE; bucket = name->lock_bucket; INSIST(bucket != DNS_ADB_INVALIDBUCKET); @@ -808,7 +822,8 @@ unlink_name(dns_adb_t *adb, dns_adbname_t *name) { INSIST(adb->name_refcnt[bucket] > 0); adb->name_refcnt[bucket]--; if (adb->name_sd[bucket] && adb->name_refcnt[bucket] == 0) - dec_adb_irefcnt(adb); + result = ISC_TRUE; + return (result); } /* @@ -824,9 +839,10 @@ link_entry(dns_adb_t *adb, int bucket, dns_adbentry_t *entry) { /* * Requires the entry's bucket be locked. */ -static inline void +static inline isc_boolean_t unlink_entry(dns_adb_t *adb, dns_adbentry_t *entry) { int bucket; + isc_boolean_t result = ISC_FALSE; bucket = entry->lock_bucket; INSIST(bucket != DNS_ADB_INVALIDBUCKET); @@ -836,7 +852,8 @@ unlink_entry(dns_adb_t *adb, dns_adbentry_t *entry) { INSIST(adb->entry_refcnt[bucket] > 0); adb->entry_refcnt[bucket]--; if (adb->entry_sd[bucket] && adb->entry_refcnt[bucket] == 0) - dec_adb_irefcnt(adb); + result = ISC_TRUE; + return (result); } static inline void @@ -852,9 +869,10 @@ violate_locking_hierarchy(isc_mutex_t *have, isc_mutex_t *want) { * The ADB _MUST_ be locked before calling. Also, exit conditions must be * checked after calling this function. */ -static void +static isc_boolean_t shutdown_names(dns_adb_t *adb) { int bucket; + isc_boolean_t result = ISC_FALSE; dns_adbname_t *name; dns_adbname_t *next_name; @@ -869,7 +887,8 @@ shutdown_names(dns_adb_t *adb) { * irefcnt ourselves, since it will not be * automatically triggered by a name being unlinked. */ - dec_adb_irefcnt(adb); + INSIST(result == ISC_FALSE); + result = dec_adb_irefcnt(adb); } else { /* * Run through the list. For each name, clean up finds @@ -879,22 +898,26 @@ shutdown_names(dns_adb_t *adb) { */ while (name != NULL) { next_name = ISC_LIST_NEXT(name, plink); - kill_name(&name, DNS_EVENT_ADBSHUTDOWN); + INSIST(result == ISC_FALSE); + result = kill_name(&name, + DNS_EVENT_ADBSHUTDOWN); name = next_name; } } UNLOCK(&adb->namelocks[bucket]); } + return (result); } /* * The ADB _MUST_ be locked before calling. Also, exit conditions must be * checked after calling this function. */ -static void +static isc_boolean_t shutdown_entries(dns_adb_t *adb) { int bucket; + isc_boolean_t result = ISC_FALSE; dns_adbentry_t *entry; dns_adbentry_t *next_entry; @@ -909,7 +932,7 @@ shutdown_entries(dns_adb_t *adb) { * irefcnt ourselves, since it will not be * automatically triggered by an entry being unlinked. */ - dec_adb_irefcnt(adb); + result = dec_adb_irefcnt(adb); } else { /* * Run through the list. Cleanup any entries not @@ -919,8 +942,10 @@ shutdown_entries(dns_adb_t *adb) { next_entry = ISC_LIST_NEXT(entry, plink); if (entry->refcnt == 0 && entry->expires != 0) { - unlink_entry(adb, entry); + result = unlink_entry(adb, entry); free_adbentry(adb, &entry); + if (result) + result = dec_adb_irefcnt(adb); } entry = next_entry; } @@ -928,6 +953,7 @@ shutdown_entries(dns_adb_t *adb) { UNLOCK(&adb->entrylocks[bucket]); } + return (result); } /* @@ -955,11 +981,12 @@ cancel_fetches_at_name(dns_adbname_t *name) { /* * Assumes the name bucket is locked. */ -static void +static isc_boolean_t clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) { dns_adbentry_t *entry; dns_adbnamehook_t *namehook; int addr_bucket; + isc_boolean_t result = ISC_FALSE; addr_bucket = DNS_ADB_INVALIDBUCKET; namehook = ISC_LIST_HEAD(*namehooks); @@ -980,7 +1007,7 @@ clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) { LOCK(&adb->entrylocks[addr_bucket]); } - dec_entry_refcnt(adb, entry, ISC_FALSE); + result = dec_entry_refcnt(adb, entry, ISC_FALSE); } /* @@ -995,6 +1022,7 @@ clean_namehooks(dns_adb_t *adb, dns_adbnamehooklist_t *namehooks) { if (addr_bucket != DNS_ADB_INVALIDBUCKET) UNLOCK(&adb->entrylocks[addr_bucket]); + return (result); } static void @@ -1183,23 +1211,33 @@ clean_finds_at_name(dns_adbname_t *name, isc_eventtype_t evtype, static inline void check_exit(dns_adb_t *adb) { isc_event_t *event; - isc_task_t *etask; - isc_boolean_t zeroirefcnt, zeroerefcnt; - /* * The caller must be holding the adb lock. */ + if (adb->shutting_down) { + /* + * If there aren't any external references either, we're + * done. Send the control event to initiate shutdown. + */ + INSIST(!adb->cevent_sent); /* Sanity check. */ + event = &adb->cevent; + isc_task_send(adb->task, &event); + adb->cevent_sent = ISC_TRUE; + } +} + +static inline isc_boolean_t +dec_adb_irefcnt(dns_adb_t *adb) { + isc_event_t *event; + isc_task_t *etask; + isc_boolean_t result = ISC_FALSE; 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) { - /* - * We're now shutdown. Send any whenshutdown events. - */ + INSIST(adb->irefcnt > 0); + adb->irefcnt--; + + if (adb->irefcnt == 0) { event = ISC_LIST_HEAD(adb->whenshutdown); while (event != NULL) { ISC_LIST_UNLINK(adb->whenshutdown, event, ev_link); @@ -1208,27 +1246,18 @@ check_exit(dns_adb_t *adb) { isc_task_sendanddetach(&etask, &event); event = ISC_LIST_HEAD(adb->whenshutdown); } - - /* - * If there aren't any external references either, we're - * done. Send the control event to initiate shutdown. - */ - if (zeroerefcnt) { - INSIST(!adb->cevent_sent); /* Sanity check. */ - event = &adb->cevent; - isc_task_send(adb->task, &event); - adb->cevent_sent = ISC_TRUE; - } } + + if (adb->irefcnt == 0 && adb->erefcnt == 0) + result = ISC_TRUE; + UNLOCK(&adb->reflock); + return (result); } static inline void -dec_adb_irefcnt(dns_adb_t *adb) { +inc_adb_irefcnt(dns_adb_t *adb) { LOCK(&adb->reflock); - - INSIST(adb->irefcnt > 0); - adb->irefcnt--; - + adb->irefcnt++; UNLOCK(&adb->reflock); } @@ -1254,10 +1283,11 @@ inc_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) { UNLOCK(&adb->entrylocks[bucket]); } -static inline void +static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) { int bucket; isc_boolean_t destroy_entry; + isc_boolean_t result = ISC_FALSE; bucket = entry->lock_bucket; @@ -1271,18 +1301,22 @@ dec_entry_refcnt(dns_adb_t *adb, dns_adbentry_t *entry, isc_boolean_t lock) { if (entry->refcnt == 0 && (adb->entry_sd[bucket] || entry->expires == 0)) { destroy_entry = ISC_TRUE; - unlink_entry(adb, entry); + result = unlink_entry(adb, entry); } if (lock) UNLOCK(&adb->entrylocks[bucket]); if (!destroy_entry) - return; + return (result); entry->lock_bucket = DNS_ADB_INVALIDBUCKET; free_adbentry(adb, &entry); + if (result) + result =dec_adb_irefcnt(adb); + + return (result); } static inline dns_adbname_t * @@ -1497,6 +1531,7 @@ new_adbfind(dns_adb_t *adb) { ISC_EVENT_INIT(&h->event, sizeof(isc_event_t), 0, 0, 0, NULL, NULL, NULL, NULL, h); + inc_adb_irefcnt(adb); h->magic = DNS_ADBFIND_MAGIC; return (h); } @@ -1686,7 +1721,7 @@ free_adbfetch6(dns_adb_t *adb, dns_adbfetch6_t **fetch) { isc_mempool_put(adb->af6mp, f); } -static inline void +static inline isc_boolean_t free_adbfind(dns_adb_t *adb, dns_adbfind_t **findp) { dns_adbfind_t *find; @@ -1704,6 +1739,7 @@ free_adbfind(dns_adb_t *adb, dns_adbfind_t **findp) { DESTROYLOCK(&find->lock); isc_mempool_put(adb->ahmp, find); + return (dec_adb_irefcnt(adb)); } /* @@ -1959,50 +1995,53 @@ shutdown_task(isc_task_t *task, isc_event_t *ev) { /* * Name bucket must be locked; adb may be locked; no other locks held. */ -static void +static isc_boolean_t check_expire_name(dns_adbname_t **namep, isc_stdtime_t now) { dns_adbname_t *name; + isc_result_t result = ISC_FALSE; INSIST(namep != NULL && DNS_ADBNAME_VALID(*namep)); name = *namep; if (NAME_HAS_V4(name) || NAME_HAS_V6(name)) - return; + return (result); if (NAME_FETCH(name)) - return; + return (result); if (!EXPIRE_OK(name->expire_v4, now)) - return; + return (result); if (!EXPIRE_OK(name->expire_v6, now)) - return; + return (result); if (!EXPIRE_OK(name->expire_target, now)) - return; + return (result); /* * The name is empty. Delete it. */ - kill_name(&name, DNS_EVENT_ADBEXPIRED); + result = kill_name(&name, DNS_EVENT_ADBEXPIRED); *namep = NULL; /* * Our caller, or one of its callers, will be calling check_exit() at * some point, so we don't need to do it here. */ + return (result); } /* * Entry bucket must be locked; adb may be locked; no other locks held. */ -static void +static isc_boolean_t check_expire_entry(dns_adb_t *adb, dns_adbentry_t **entryp, isc_stdtime_t now) { dns_adbentry_t *entry; isc_boolean_t expire; + isc_boolean_t result = ISC_FALSE; INSIST(entryp != NULL && DNS_ADBENTRY_VALID(*entryp)); entry = *entryp; if (entry->refcnt != 0) - return; + return (result); if (adb->overmem) { isc_uint32_t val; @@ -2014,49 +2053,57 @@ check_expire_entry(dns_adb_t *adb, dns_adbentry_t **entryp, isc_stdtime_t now) expire = ISC_FALSE; if (entry->expires == 0 || (! expire && entry->expires > now)) - return; + return (result); /* * The entry is not in use. Delete it. */ DP(DEF_LEVEL, "killing entry %p", entry); INSIST(ISC_LINK_LINKED(entry, plink)); - unlink_entry(adb, entry); + result = unlink_entry(adb, entry); free_adbentry(adb, &entry); + if (result) + dec_adb_irefcnt(adb); *entryp = NULL; + return (result); } /* * ADB must be locked, and no other locks held. */ -static void +static isc_boolean_t cleanup_names(dns_adb_t *adb, int bucket, isc_stdtime_t now) { dns_adbname_t *name; dns_adbname_t *next_name; + isc_result_t result = ISC_FALSE; DP(CLEAN_LEVEL, "cleaning name bucket %d", bucket); LOCK(&adb->namelocks[bucket]); if (adb->name_sd[bucket]) { UNLOCK(&adb->namelocks[bucket]); - return; + return (result); } name = ISC_LIST_HEAD(adb->names[bucket]); while (name != NULL) { next_name = ISC_LIST_NEXT(name, plink); - check_expire_namehooks(name, now, adb->overmem); - check_expire_name(&name, now); + INSIST(result == ISC_FALSE); + result = check_expire_namehooks(name, now, adb->overmem); + if (!result) + result = check_expire_name(&name, now); name = next_name; } UNLOCK(&adb->namelocks[bucket]); + return (result); } /* * ADB must be locked, and no other locks held. */ -static void +static isc_boolean_t cleanup_entries(dns_adb_t *adb, int bucket, isc_stdtime_t now) { dns_adbentry_t *entry, *next_entry; + isc_boolean_t result = ISC_FALSE; DP(CLEAN_LEVEL, "cleaning entry bucket %d", bucket); @@ -2064,10 +2111,12 @@ cleanup_entries(dns_adb_t *adb, int bucket, isc_stdtime_t now) { entry = ISC_LIST_HEAD(adb->entries[bucket]); while (entry != NULL) { next_entry = ISC_LIST_NEXT(entry, plink); - check_expire_entry(adb, &entry, now); + INSIST(result == ISC_FALSE); + result = check_expire_entry(adb, &entry, now); entry = next_entry; } UNLOCK(&adb->entrylocks[bucket]); + return (result); } static void @@ -2090,8 +2139,10 @@ timer_cleanup(isc_task_t *task, isc_event_t *ev) { /* * Call our cleanup routines. */ - cleanup_names(adb, adb->next_cleanbucket, now); - cleanup_entries(adb, adb->next_cleanbucket, now); + INSIST(cleanup_names(adb, adb->next_cleanbucket, now) == + ISC_FALSE); + INSIST(cleanup_entries(adb, adb->next_cleanbucket, now) == + ISC_FALSE); /* * Set the next bucket to be cleaned. @@ -2346,7 +2397,7 @@ dns_adb_attach(dns_adb_t *adb, dns_adb_t **adbx) { void dns_adb_detach(dns_adb_t **adbx) { dns_adb_t *adb; - isc_boolean_t zeroerefcnt; + isc_boolean_t need_exit_check; REQUIRE(adbx != NULL && DNS_ADB_VALID(*adbx)); @@ -2357,13 +2408,13 @@ dns_adb_detach(dns_adb_t **adbx) { LOCK(&adb->reflock); adb->erefcnt--; - zeroerefcnt = ISC_TF(adb->erefcnt == 0); + need_exit_check = ISC_TF(adb->erefcnt == 0 && adb->irefcnt == 0); UNLOCK(&adb->reflock); - if (zeroerefcnt) { + if (need_exit_check) { LOCK(&adb->lock); - check_exit(adb); INSIST(adb->shutting_down); + check_exit(adb); UNLOCK(&adb->lock); } } @@ -2388,7 +2439,6 @@ dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp) { LOCK(&adb->reflock); zeroirefcnt = ISC_TF(adb->irefcnt == 0); - UNLOCK(&adb->reflock); if (adb->shutting_down && zeroirefcnt && isc_mempool_getallocated(adb->ahmp) == 0) { @@ -2404,11 +2454,13 @@ dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp) { ISC_LIST_APPEND(adb->whenshutdown, event, ev_link); } + UNLOCK(&adb->reflock); UNLOCK(&adb->lock); } void dns_adb_shutdown(dns_adb_t *adb) { + isc_boolean_t need_check_exit; /* * Shutdown 'adb'. @@ -2419,9 +2471,11 @@ dns_adb_shutdown(dns_adb_t *adb) { if (!adb->shutting_down) { adb->shutting_down = ISC_TRUE; isc_mem_setwater(adb->mctx, water, adb, 0, 0); - shutdown_names(adb); - shutdown_entries(adb); - check_exit(adb); + need_check_exit = shutdown_names(adb); + if (!need_check_exit) + need_check_exit = shutdown_entries(adb); + if (need_check_exit) + check_exit(adb); } UNLOCK(&adb->lock); @@ -2508,7 +2562,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, if (adb->name_sd[bucket]) { DP(DEF_LEVEL, "dns_adb_createfind: returning ISC_R_SHUTTINGDOWN"); - free_adbfind(adb, &find); + INSIST(free_adbfind(adb, &find) == ISC_FALSE); result = ISC_R_SHUTTINGDOWN; goto out; } @@ -2519,7 +2573,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, if (adbname == NULL) { adbname = new_adbname(adb, name); if (adbname == NULL) { - free_adbfind(adb, &find); + INSIST(free_adbfind(adb, &find) == ISC_FALSE); result = ISC_R_NOMEMORY; goto out; } @@ -2535,7 +2589,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, /* * Expire old entries, etc. */ - check_expire_namehooks(adbname, now, adb->overmem); + INSIST(check_expire_namehooks(adbname, now, adb->overmem) == ISC_FALSE); /* * Do we know that the name is an alias? @@ -2818,7 +2872,7 @@ dns_adb_destroyfind(dns_adbfind_t **findp) { entry = ai->entry; ai->entry = NULL; INSIST(DNS_ADBENTRY_VALID(entry)); - dec_entry_refcnt(adb, entry, ISC_TRUE); + INSIST(dec_entry_refcnt(adb, entry, ISC_TRUE) == ISC_FALSE); free_adbaddrinfo(adb, &ai); ai = ISC_LIST_HEAD(find->list); } @@ -2831,8 +2885,8 @@ dns_adb_destroyfind(dns_adbfind_t **findp) { * lock is destroyed. */ LOCK(&adb->lock); - free_adbfind(adb, &find); - check_exit(adb); + if (free_adbfind(adb, &find)) + check_exit(adb); UNLOCK(&adb->lock); } @@ -3427,14 +3481,7 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) { free_adbfetch(adb, &fetch); isc_event_free(&ev); - kill_name(&name, DNS_EVENT_ADBCANCELED); - - /* - * If we're shutting down and this bucket is empty, we need - * to call check_exit() to see if we're done. - */ - if (adb->name_sd[bucket] && adb->name_refcnt[bucket] == 0) - want_check_exit = ISC_TRUE; + want_check_exit = kill_name(&name, DNS_EVENT_ADBCANCELED); UNLOCK(&adb->namelocks[bucket]); @@ -3597,14 +3644,7 @@ fetch_callback_a6(isc_task_t *task, isc_event_t *ev) { free_adbfetch6(adb, &fetch); isc_event_free(&ev); - kill_name(&name, DNS_EVENT_ADBCANCELED); - - /* - * If we're shutting down and this bucket is empty, we need - * to call check_exit() to see if we're done. - */ - if (adb->name_sd[bucket] && adb->name_refcnt[bucket] == 0) - want_check_exit = ISC_TRUE; + want_check_exit = kill_name(&name, DNS_EVENT_ADBCANCELED); UNLOCK(&adb->namelocks[bucket]); @@ -4061,9 +4101,7 @@ dns_adb_freeaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **addrp) { entry->expires = now + 1800; /* XXXRTH */ - dec_entry_refcnt(adb, entry, ISC_FALSE); - if (adb->entry_sd[bucket] && adb->entry_refcnt[bucket] == 0) - want_check_exit = ISC_TRUE; + want_check_exit = dec_entry_refcnt(adb, entry, ISC_FALSE); UNLOCK(&adb->entrylocks[bucket]); @@ -4089,8 +4127,8 @@ dns_adb_flush(dns_adb_t *adb) { /* * Call our cleanup routines. */ - cleanup_names(adb, i, INT_MAX); - cleanup_entries(adb, i, INT_MAX); + INSIST(cleanup_names(adb, i, INT_MAX) == ISC_FALSE); + INSIST(cleanup_entries(adb, i, INT_MAX) == ISC_FALSE); } #ifdef DUMP_ADB_AFTER_CLEANING @@ -4116,7 +4154,8 @@ dns_adb_flushname(dns_adb_t *adb, dns_name_t *name) { nextname = ISC_LIST_NEXT(adbname, plink); if (!NAME_DEAD(adbname) && dns_name_equal(name, &adbname->name)) { - kill_name(&adbname, DNS_EVENT_ADBCANCELED); + INSIST(kill_name(&adbname, DNS_EVENT_ADBCANCELED) + == ISC_FALSE); } adbname = nextname; }