]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add system test for delegdb size preservation across `rndc flush` 12101/head
authorColin Vidal <colin@isc.org>
Wed, 27 May 2026 08:50:42 +0000 (10:50 +0200)
committerColin Vidal <colin@isc.org>
Thu, 28 May 2026 11:59:38 +0000 (13:59 +0200)
Test that flushing the delegdb via `rndc flush` preserves its
configured size limit.  The test checks delegdb watermarks after
`named` startup, flushes caches, and verifies that the delegdb
watermarks are correctly restored afterwards.

To distinguish between the previous `delegdb` memory contexts and the
new ones, we need to know exactly when the previous `delegdb` memory
contexts are removed (this is not immediate, since those are removed
during RCU reclamation phase). A trace is therefore added when a memory
context is destroyed, if `ISC_MEM_DEBUGTRACE` is set.

bin/tests/system/delegdb_flush/ns1/named.args [new file with mode: 0644]
bin/tests/system/delegdb_flush/ns1/named.conf.j2 [new file with mode: 0644]
bin/tests/system/delegdb_flush/tests_delegdb_flush.py [new file with mode: 0644]
lib/isc/mem.c

diff --git a/bin/tests/system/delegdb_flush/ns1/named.args b/bin/tests/system/delegdb_flush/ns1/named.args
new file mode 100644 (file)
index 0000000..6a68cc8
--- /dev/null
@@ -0,0 +1 @@
+-m trace -c named.conf -d 99 -D delegdb_flush-ns1 -g
diff --git a/bin/tests/system/delegdb_flush/ns1/named.conf.j2 b/bin/tests/system/delegdb_flush/ns1/named.conf.j2
new file mode 100644 (file)
index 0000000..e920488
--- /dev/null
@@ -0,0 +1,19 @@
+options {
+       port @PORT@;
+       pid-file "named.pid";
+       listen-on { 10.53.0.1; };
+       max-cache-size 8000;
+};
+
+statistics-channels {
+       inet 10.53.0.1 port @EXTRAPORT1@;
+};
+
+key rndc_key {
+       secret "1234abcd8765";
+       algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+       inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/delegdb_flush/tests_delegdb_flush.py b/bin/tests/system/delegdb_flush/tests_delegdb_flush.py
new file mode 100644 (file)
index 0000000..dd72971
--- /dev/null
@@ -0,0 +1,65 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0.  If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import os
+
+import requests
+
+import isctest.mark
+
+pytestmark = [isctest.mark.with_json_c, isctest.mark.with_developer]
+
+
+def get_delegdb_watermarks(ip, port):
+    watermarks = []
+    r = requests.get(f"http://{ip}:{port}/json/v1/mem", timeout=600)
+    assert r.status_code == 200
+    mem = r.json()["memory"]
+    for c in mem["contexts"]:
+        if c["name"] == "dns_delegdb":
+            watermarks.append((c["id"], c["lowater"], c["hiwater"]))
+    return watermarks
+
+
+def check_watermarks(watermarks1, watermarks2):
+    if watermarks2 is not None:
+        assert len(watermarks1) == len(watermarks2)
+    for i, (id1, lowater1, hiwater1) in enumerate(watermarks1):
+        assert lowater1 > 0
+        assert hiwater1 > 0
+        if watermarks2 is not None:
+            id2, lowater2, hiwater2 = watermarks2[i]
+            assert id1 != id2
+            assert lowater1 == lowater2
+            assert hiwater1 == hiwater2
+
+
+def test_delegdb_flush(ns1):
+    statsport = os.getenv("EXTRAPORT1")
+
+    watermarks1 = get_delegdb_watermarks(ns1.ip, statsport)
+    check_watermarks(watermarks1, None)
+
+    with ns1.watch_log_from_here() as watcher:
+        ns1.rndc("flush")
+        watcher.wait_for_sequence(
+            ["flushing caches in all views succeeded", "loop exclusive mode: ended"]
+        )
+
+    # The previous delegdb contexts can still be hanging around for a little
+    # bit, until RCU reclamation run and it actually gets detached/freed.
+    for watermarks in watermarks1:
+        id1, _, _ = watermarks
+        with ns1.watch_log_from_start() as watcher:
+            watcher.wait_for_line(f"destroyed mctx {id1}")
+
+    watermarks2 = get_delegdb_watermarks(ns1.ip, statsport)
+    check_watermarks(watermarks1, watermarks2)
index 70c8b6b86e2604ec7b8621eb9e888b2b0c34c980..fd594d8ebe4ad39872dd53cb566562cbb4a0636e 100644 (file)
@@ -700,6 +700,12 @@ mem_destroy(isc_mem_t *ctx) {
 
        isc_mutex_destroy(&ctx->lock);
 
+#if ISC_MEM_TRACKLINES
+       if ((mem_debugging & ISC_MEM_DEBUGTRACE) != 0) {
+               fprintf(stderr, "destroyed mctx %p\n", ctx);
+       }
+#endif /* ISC_MEM_TRACKLINES */
+
        sdallocx(ctx, sizeof(*ctx), ctx->jemalloc_flags);
 }