]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Detach the views in zone_shutdown(), not in zone_free()
authorOndřej Surý <ondrej@isc.org>
Tue, 17 Jan 2023 06:18:16 +0000 (07:18 +0100)
committerOndřej Surý <ondrej@isc.org>
Tue, 17 Jan 2023 20:48:30 +0000 (21:48 +0100)
The .view (and possibly .prev_view) would be kept attached to the
removed zone until the zone is fully removed from the memory in
zone_free().  If this process is delayed because server is busy
something else like doing constant `rndc reconfig`, it could take
seconds to detach the view, possibly keeping multiple dead views in the
memory.  This could quickly lead to a massive memory bloat.

Release the views early in the zone_shutdown() call, and don't wait
until the zone is freed.

lib/dns/zone.c

index 28aeb00e04723bbd1cb02e16fe3c92d3d3a6f71b..411756d9cbe9cc3c3833be24ce3d064f799b8ab8 100644 (file)
@@ -1246,6 +1246,8 @@ zone_free(dns_zone_t *zone) {
        INSIST(zone->readio == NULL);
        INSIST(zone->statelist == NULL);
        INSIST(zone->writeio == NULL);
+       INSIST(zone->view == NULL);
+       INSIST(zone->prev_view == NULL);
 
        if (zone->task != NULL) {
                isc_task_detach(&zone->task);
@@ -1253,12 +1255,6 @@ zone_free(dns_zone_t *zone) {
        if (zone->loadtask != NULL) {
                isc_task_detach(&zone->loadtask);
        }
-       if (zone->view != NULL) {
-               dns_view_weakdetach(&zone->view);
-       }
-       if (zone->prev_view != NULL) {
-               dns_view_weakdetach(&zone->prev_view);
-       }
 
        /* Unmanaged objects */
        while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
@@ -14737,6 +14733,15 @@ zone_shutdown(void *arg) {
 
        LOCK_ZONE(zone);
        INSIST(zone != zone->raw);
+
+       /* Detach the views early, we don't need them anymore */
+       if (zone->view != NULL) {
+               dns_view_weakdetach(&zone->view);
+       }
+       if (zone->prev_view != NULL) {
+               dns_view_weakdetach(&zone->prev_view);
+       }
+
        if (linked) {
                isc_refcount_decrement(&zone->irefs);
        }