mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +00:00
Fixed multiple shutdown cleanup bugs in the zone object. This
involved extensive restructuring of the reference counting of zones and related objects. Zones now attach to their views. To avoid a circular dependency that would keep views from ever shutting down, this is done using the new functions dns_view_weakattach() / dns_view_weakdetach() which guarantee that the view will not be freed but still allow it to be shut down. The zones themselves now only have a single reference count, with similar "weak" semantics. Managed zones must now be shut down explicitly by calling dns_zone_shutdown(). To shut down all zones in a zone table, call dns_zt_shutdown(). The zone manager is now reference counted, weakly. To shut down the zone manager, you must explicitly call dns_zonemgr_shutdown().
This commit is contained in:
@@ -121,6 +121,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
|
||||
view->frozen = ISC_FALSE;
|
||||
view->task = NULL;
|
||||
view->references = 1;
|
||||
view->weakrefs = 0;
|
||||
view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN|
|
||||
DNS_VIEWATTR_REQSHUTDOWN);
|
||||
view->statickeys = NULL;
|
||||
@@ -188,31 +189,11 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
dns_view_attach(dns_view_t *source, dns_view_t **targetp) {
|
||||
|
||||
/*
|
||||
* Attach '*targetp' to 'source'.
|
||||
*/
|
||||
|
||||
REQUIRE(DNS_VIEW_VALID(source));
|
||||
REQUIRE(targetp != NULL && *targetp == NULL);
|
||||
|
||||
LOCK(&source->lock);
|
||||
|
||||
INSIST(source->references > 0);
|
||||
source->references++;
|
||||
INSIST(source->references != 0);
|
||||
|
||||
UNLOCK(&source->lock);
|
||||
|
||||
*targetp = source;
|
||||
}
|
||||
|
||||
static inline void
|
||||
destroy(dns_view_t *view) {
|
||||
REQUIRE(!ISC_LINK_LINKED(view, link));
|
||||
REQUIRE(view->references == 0);
|
||||
REQUIRE(view->weakrefs == 0);
|
||||
REQUIRE(RESSHUTDOWN(view));
|
||||
REQUIRE(ADBSHUTDOWN(view));
|
||||
REQUIRE(REQSHUTDOWN(view));
|
||||
@@ -257,22 +238,35 @@ all_done(dns_view_t *view) {
|
||||
* Caller must be holding the view lock.
|
||||
*/
|
||||
|
||||
if (view->references == 0 && RESSHUTDOWN(view) &&
|
||||
ADBSHUTDOWN(view) && REQSHUTDOWN(view))
|
||||
if (view->references == 0 && view->weakrefs == 0 &&
|
||||
RESSHUTDOWN(view) && ADBSHUTDOWN(view) && REQSHUTDOWN(view))
|
||||
return (ISC_TRUE);
|
||||
|
||||
return (ISC_FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
dns_view_attach(dns_view_t *source, dns_view_t **targetp) {
|
||||
|
||||
REQUIRE(DNS_VIEW_VALID(source));
|
||||
REQUIRE(targetp != NULL && *targetp == NULL);
|
||||
|
||||
LOCK(&source->lock);
|
||||
|
||||
INSIST(source->references > 0);
|
||||
source->references++;
|
||||
INSIST(source->references != 0);
|
||||
|
||||
UNLOCK(&source->lock);
|
||||
|
||||
*targetp = source;
|
||||
}
|
||||
|
||||
void
|
||||
dns_view_detach(dns_view_t **viewp) {
|
||||
dns_view_t *view;
|
||||
isc_boolean_t done = ISC_FALSE;
|
||||
|
||||
/*
|
||||
* Detach '*viewp' from its view.
|
||||
*/
|
||||
|
||||
REQUIRE(viewp != NULL);
|
||||
view = *viewp;
|
||||
REQUIRE(DNS_VIEW_VALID(view));
|
||||
@@ -288,6 +282,7 @@ dns_view_detach(dns_view_t **viewp) {
|
||||
dns_adb_shutdown(view->adb);
|
||||
if (!REQSHUTDOWN(view))
|
||||
dns_requestmgr_shutdown(view->requestmgr);
|
||||
dns_zt_shutdown(view->zonetable);
|
||||
done = all_done(view);
|
||||
}
|
||||
UNLOCK(&view->lock);
|
||||
@@ -298,6 +293,42 @@ dns_view_detach(dns_view_t **viewp) {
|
||||
destroy(view);
|
||||
}
|
||||
|
||||
void
|
||||
dns_view_weakattach(dns_view_t *source, dns_view_t **targetp) {
|
||||
|
||||
REQUIRE(DNS_VIEW_VALID(source));
|
||||
REQUIRE(targetp != NULL && *targetp == NULL);
|
||||
|
||||
LOCK(&source->lock);
|
||||
source->weakrefs++;
|
||||
UNLOCK(&source->lock);
|
||||
|
||||
*targetp = source;
|
||||
}
|
||||
|
||||
void
|
||||
dns_view_weakdetach(dns_view_t **viewp) {
|
||||
dns_view_t *view;
|
||||
isc_boolean_t done = ISC_FALSE;
|
||||
|
||||
REQUIRE(viewp != NULL);
|
||||
view = *viewp;
|
||||
REQUIRE(DNS_VIEW_VALID(view));
|
||||
|
||||
LOCK(&view->lock);
|
||||
|
||||
INSIST(view->weakrefs > 0);
|
||||
view->weakrefs--;
|
||||
done = all_done(view);
|
||||
|
||||
UNLOCK(&view->lock);
|
||||
|
||||
*viewp = NULL;
|
||||
|
||||
if (done)
|
||||
destroy(view);
|
||||
}
|
||||
|
||||
static void
|
||||
resolver_shutdown(isc_task_t *task, isc_event_t *event) {
|
||||
dns_view_t *view = event->ev_arg;
|
||||
|
Reference in New Issue
Block a user