From: Libor Peltan Date: Mon, 9 Aug 2021 09:27:03 +0000 (+0200) Subject: catalog: avoid opening catalogDB from worker threads... X-Git-Tag: v3.1.1~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e3b4382800a82b3df575dbb5e88928eaafb9907a;p=thirdparty%2Fknot-dns.git catalog: avoid opening catalogDB from worker threads... ...in case of concurrency, it might lead to server crash on startup this way, catalogDB is only opened from main thread in advance --- diff --git a/src/knot/catalog/catalog_update.c b/src/knot/catalog/catalog_update.c index effaa8db9f..1f2f259bc8 100644 --- a/src/knot/catalog/catalog_update.c +++ b/src/knot/catalog/catalog_update.c @@ -350,14 +350,9 @@ static int del_all_cb(const knot_dname_t *member, const knot_dname_t *owner, int catalog_update_del_all(catalog_update_t *u, catalog_t *cat, const knot_dname_t *zone) { - int ret = catalog_open(cat); - if (ret != KNOT_EOK) { - return ret; - } - pthread_mutex_lock(&u->mutex); del_all_ctx_t ctx = { zone, u }; - ret = catalog_apply(cat, NULL, del_all_cb, &ctx, false); + int ret = catalog_apply(cat, NULL, del_all_cb, &ctx, false); pthread_mutex_unlock(&u->mutex); return ret; } diff --git a/src/knot/zone/zonedb-load.c b/src/knot/zone/zonedb-load.c index 7f7f0b1c0f..a8152f28d1 100644 --- a/src/knot/zone/zonedb-load.c +++ b/src/knot/zone/zonedb-load.c @@ -161,6 +161,11 @@ static zone_t *create_zone_new(conf_t *conf, const knot_dname_t *name, zone_free(&zone); return NULL; } + } else if (conf_opt(&role) == CATALOG_ROLE_INTERPRET) { + ret = catalog_open(&server->catalog); + if (ret != KNOT_EOK) { + log_error("failed to open catalog database (%s)", knot_strerror(ret)); + } } if (zone_expired(zone)) { diff --git a/tests-extra/tests/catalog/multi/data/catalog1.zone b/tests-extra/tests/catalog/multi/data/catalog1.zone new file mode 100644 index 0000000000..1d497600d4 --- /dev/null +++ b/tests-extra/tests/catalog/multi/data/catalog1.zone @@ -0,0 +1,7 @@ +$ORIGIN catalog1. +$TTL 0 + +@ SOA ns admin 1 25 25 80 600 + NS ns +ns AAAA ::0 +version TXT "2" diff --git a/tests-extra/tests/catalog/multi/data/catalog2.zone b/tests-extra/tests/catalog/multi/data/catalog2.zone new file mode 100644 index 0000000000..b392528cfa --- /dev/null +++ b/tests-extra/tests/catalog/multi/data/catalog2.zone @@ -0,0 +1,7 @@ +$ORIGIN catalog2. +$TTL 0 + +@ SOA ns admin 1 25 25 80 600 + NS ns +ns AAAA ::0 +version TXT "2" diff --git a/tests-extra/tests/catalog/multi/data/catalog3.zone b/tests-extra/tests/catalog/multi/data/catalog3.zone new file mode 100644 index 0000000000..6a92639464 --- /dev/null +++ b/tests-extra/tests/catalog/multi/data/catalog3.zone @@ -0,0 +1,7 @@ +$ORIGIN catalog3. +$TTL 0 + +@ SOA ns admin 1 25 25 80 600 + NS ns +ns AAAA ::0 +version TXT "2" diff --git a/tests-extra/tests/catalog/multi/test.py b/tests-extra/tests/catalog/multi/test.py new file mode 100644 index 0000000000..bf6129ec9e --- /dev/null +++ b/tests-extra/tests/catalog/multi/test.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 + +'''Test of multiple Catalog zones.''' + +from dnstest.test import Test +from dnstest.utils import set_err, detail_log +import dnstest.params + +import glob +import shutil +from subprocess import DEVNULL, PIPE, Popen +import subprocess +import random +import dns + +t = Test() + +def cat_zf(server, zone): + return server.zones[zone.name].zfile.path + +def upd_cat_zf(server, zone, member): + uniq = str(random.randint(1000000, 9999999)) + ptr = "%s.zones.%s 0 PTR %s" % (uniq, zone.name, member) + with open(cat_zf(server, zone), "a") as zf: + zf.write(ptr + "\n") + +def check_exists(server, member, expect_exists, msg): + resp = server.dig(member, "SOA") + rc = dns.rcode.to_text(resp.resp.rcode()) + if rc == "SERVFAIL": + if not expect_exists: + set_err("%s: exists %s" % (msg, member)) + elif rc == "REFUSED": + if expect_exists: + set_err("%s: not exists %s" % (msg, member)) + else: + set_err("Unexpected rcode %s" % rc) + +master = t.server("knot") + +# Zone setup +zone = t.zone("example.com.") + t.zone("catalog1.", storage=".") + t.zone("catalog2.", storage=".") + t.zone("catalog3.", storage=".") + +t.link(zone, master) + +master.zones["catalog1."].catalog = True +master.zones["catalog2."].catalog = True +master.zones["catalog3."].catalog = True + +t.start() +t.sleep(5) + +upd_cat_zf(master, zone[1], "member1.example.") +upd_cat_zf(master, zone[2], "member2.example.") +upd_cat_zf(master, zone[3], "member3.example.") + +master.ctl("zone-reload %s" % zone[1].name) +t.sleep(5) + +check_exists(master, "member1.example.", True, "First") +check_exists(master, "member2.example.", False, "First") +check_exists(master, "member3.example.", False, "First") + +master.ctl("zone-reload %s" % zone[2].name) +t.sleep(5) + +check_exists(master, "member1.example.", True, "Second") +check_exists(master, "member2.example.", True, "Second") +check_exists(master, "member3.example.", False, "Second") + +t.end()