diff --git a/bin/named/server.c b/bin/named/server.c index f3dffbb625..c34fd28a8b 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -8142,7 +8142,7 @@ apply_configuration(cfg_parser_t *configparser, cfg_obj_t *config, uint32_t max; uint64_t initial, idle, keepalive, advertised, primaries; bool loadbalancesockets; - bool exclusive = true; + bool exclusive = false; dns_aclenv_t *env = ns_interfacemgr_getaclenv(named_g_server->interfacemgr); cfg_aclconfctx_t *tmpaclctx, *aclctx = NULL; @@ -8199,6 +8199,7 @@ apply_configuration(cfg_parser_t *configparser, cfg_obj_t *config, isc_tlsctx_cache_create(isc_g_mctx, &tlsctx_client_cache); /* Ensure exclusive access to configuration data. */ + exclusive = true; isc_loopmgr_pause(); /* @@ -9300,10 +9301,6 @@ cleanup_bindkeys_parser: cfg_parser_destroy(&bindkeys_parser); } - if (exclusive) { - isc_loopmgr_resume(); - } - /* * Detach the TLS client context (whether the one created at the * begining of this function, or the previous running one) @@ -9311,6 +9308,9 @@ cleanup_bindkeys_parser: isc_tlsctx_cache_detach(&tlsctx_client_cache); cleanup_viewlist: + isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, + ISC_LOG_DEBUG(3), "apply_configuration: detaching views"); + ISC_LIST_FOREACH(viewlist, view, link) { ISC_LIST_UNLINK(viewlist, view, link); if (result == ISC_R_SUCCESS && strcmp(view->name, "_bind") != 0) @@ -9321,6 +9321,10 @@ cleanup_viewlist: dns_view_detach(&view); } + if (exclusive) { + isc_loopmgr_resume(); + } + cleanup_kasplist: ISC_LIST_FOREACH(kasplist, kasp, link) { ISC_LIST_UNLINK(kasplist, kasp, link); diff --git a/bin/tests/system/configloading/ns1/named.conf.j2 b/bin/tests/system/configloading/ns1/named.conf.j2 index 6c85c1df5e..ca1c1630a1 100644 --- a/bin/tests/system/configloading/ns1/named.conf.j2 +++ b/bin/tests/system/configloading/ns1/named.conf.j2 @@ -11,7 +11,7 @@ * information regarding copyright ownership. */ -// NS2 +{% set wrongoption = wrongoption | default(False) %} options { port @PORT@; @@ -30,9 +30,15 @@ controls { inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; }; - -zone "example." { - type primary; - file "example.db"; +view "default" { + zone "example." { + type primary; + file "example.db"; + }; + /* + * failure to reconfig must occurs during configuration of the views + */ + {% if wrongoption %} + forwarders port 9999999 { 127.0.0.1; }; + {% endif %} }; - diff --git a/bin/tests/system/configloading/tests_configloading.py b/bin/tests/system/configloading/tests_configloading.py index 92a1907741..1b74e31b33 100644 --- a/bin/tests/system/configloading/tests_configloading.py +++ b/bin/tests/system/configloading/tests_configloading.py @@ -9,6 +9,11 @@ # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. +import re + + +import isctest + def test_configloading_log(ns1): """ @@ -39,3 +44,28 @@ def test_configloading_log(ns1): with ns1.watch_log_from_here() as watcher: ns1.rndc("reload") watcher.wait_for_sequence(log_sequence) + + +def test_reload_fails_log(ns1, templates): + """ + This test ensures that when a reconfig fails during view configuration (or + after), views/zones (which are newly created view/zones which won't be used + and local of apply_configuration) are detached (and freed) before the + exclusive mode is released + """ + + log_sequence = [ + "apply_configuration", + "loop exclusive mode: starting", + "apply_configuration: configure_views", + re.compile(r".*port '9999999' out of range"), + "apply_configuration: detaching views", + "loop exclusive mode: ending", + ] + + with ns1.watch_log_from_here() as watcher: + templates.render("ns1/named.conf", {"wrongoption": True}) + try: + ns1.rndc("reload") + except isctest.rndc.RNDCException: + watcher.wait_for_sequence(log_sequence)