diff --git a/bin/named/server.c b/bin/named/server.c index 73d8fd1fde..6b6f020017 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -3189,6 +3189,7 @@ configure_catz(dns_view_t *view, dns_view_t *pview, const cfg_obj_t *config, } if (old != NULL) { + dns_catz_shutdown_catzs(view->catzs); dns_catz_detach_catzs(&view->catzs); dns_catz_attach_catzs(pview->catzs, &view->catzs); dns_catz_detach_catzs(&pview->catzs); diff --git a/lib/dns/catz.c b/lib/dns/catz.c index 4edc8c80ec..9b48acdde8 100644 --- a/lib/dns/catz.c +++ b/lib/dns/catz.c @@ -127,6 +127,7 @@ struct dns_catz_zones { isc_timermgr_t *timermgr; dns_view_t *view; isc_task_t *updater; + atomic_bool shuttingdown; }; void @@ -889,6 +890,22 @@ dns_catz_get_zone(dns_catz_zones_t *catzs, const dns_name_t *name) { return (found); } +static void +dns__catz_shutdown(dns_catz_zone_t *catz) { + /* lock must be locked */ + if (catz->updatetimer != NULL) { + isc_result_t result; + + /* Don't wait for timer to trigger for shutdown */ + result = isc_timer_reset(catz->updatetimer, + isc_timertype_inactive, NULL, NULL, + true); + RUNTIME_CHECK(result == ISC_R_SUCCESS); + } + + dns_catz_detach_catz(&catz); +} + static void dns__catz_zone_destroy(dns_catz_zone_t *catz) { isc_mem_t *mctx = catz->catzs->mctx; @@ -956,22 +973,9 @@ dns__catz_zone_destroy(dns_catz_zone_t *catz) { static void dns__catz_zones_destroy(dns_catz_zones_t *catzs) { - if (catzs->zones != NULL) { - isc_ht_iter_t *iter = NULL; - isc_result_t result; - isc_ht_iter_create(catzs->zones, &iter); - for (result = isc_ht_iter_first(iter); result == ISC_R_SUCCESS;) - { - dns_catz_zone_t *zone = NULL; - isc_ht_iter_current(iter, (void **)&zone); - result = isc_ht_iter_delcurrent_next(iter); - dns_catz_detach_catz(&zone); - } - INSIST(result == ISC_R_NOMORE); - isc_ht_iter_destroy(&iter); - INSIST(isc_ht_count(catzs->zones) == 0); - isc_ht_destroy(&catzs->zones); - } + REQUIRE(atomic_load(&catzs->shuttingdown)); + REQUIRE(catzs->zones == NULL); + catzs->magic = 0; isc_task_destroy(&catzs->updater); isc_mutex_destroy(&catzs->lock); @@ -980,6 +984,36 @@ dns__catz_zones_destroy(dns_catz_zones_t *catzs) { isc_mem_putanddetach(&catzs->mctx, catzs, sizeof(*catzs)); } +void +dns_catz_shutdown_catzs(dns_catz_zones_t *catzs) { + REQUIRE(DNS_CATZ_ZONES_VALID(catzs)); + + if (!atomic_compare_exchange_strong(&catzs->shuttingdown, + &(bool){ false }, true)) + { + return; + } + + LOCK(&catzs->lock); + if (catzs->zones != NULL) { + isc_ht_iter_t *iter = NULL; + isc_result_t result; + isc_ht_iter_create(catzs->zones, &iter); + for (result = isc_ht_iter_first(iter); result == ISC_R_SUCCESS;) + { + dns_catz_zone_t *catz = NULL; + isc_ht_iter_current(iter, (void **)&catz); + result = isc_ht_iter_delcurrent_next(iter); + dns__catz_shutdown(catz); + } + INSIST(result == ISC_R_NOMORE); + isc_ht_iter_destroy(&iter); + INSIST(isc_ht_count(catzs->zones) == 0); + isc_ht_destroy(&catzs->zones); + } + UNLOCK(&catzs->lock); +} + #ifdef DNS_CATZ_TRACE ISC_REFCOUNT_TRACE_IMPL(dns_catz_zone, dns__catz_zone_destroy); ISC_REFCOUNT_TRACE_IMPL(dns_catz_zones, dns__catz_zones_destroy); @@ -2120,6 +2154,10 @@ dns_catz_update_from_db(dns_db_t *db, dns_catz_zones_t *catzs) { REQUIRE(DNS_DB_VALID(db)); REQUIRE(DNS_CATZ_ZONES_VALID(catzs)); + if (atomic_load(&catzs->shuttingdown)) { + return; + } + dns_name_format(&db->origin, bname, DNS_NAME_FORMATSIZE); /* diff --git a/lib/dns/include/dns/catz.h b/lib/dns/include/dns/catz.h index 049d76e622..5c6282b669 100644 --- a/lib/dns/include/dns/catz.h +++ b/lib/dns/include/dns/catz.h @@ -437,6 +437,16 @@ dns_catz_get_iterator(dns_catz_zone_t *catz, isc_ht_iter_t **itp); * */ +void +dns_catz_shutdown_catzs(dns_catz_zones_t *catzs); +/*%< + * Shut down the catalog zones. + * + * Requires: + * \li 'catzs' is a valid dns_catz_zones_t. + * + */ + #ifdef DNS_CATZ_TRACE /* Compatibility macros */ #define dns_catz_attach_catz(catz, catzp) \ diff --git a/lib/dns/view.c b/lib/dns/view.c index 755f69c8e7..7f4280c563 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -423,6 +423,7 @@ destroy(dns_view_t *view) { dns_rpz_detach_rpzs(&view->rpzs); } if (view->catzs != NULL) { + dns_catz_shutdown_catzs(view->catzs); dns_catz_detach_catzs(&view->catzs); } for (dlzdb = ISC_LIST_HEAD(view->dlz_searched); dlzdb != NULL; @@ -680,6 +681,7 @@ view_flushanddetach(dns_view_t **viewp, bool flush) { } } if (view->catzs != NULL) { + dns_catz_shutdown_catzs(view->catzs); dns_catz_detach_catzs(&view->catzs); } if (view->ntatable_priv != NULL) {