server: abort possible open zone transaction when shutdown

This commit is contained in:
Daniel Salzman 2019-12-05 15:25:42 +01:00
parent db95867f24
commit 356310126e
6 changed files with 43 additions and 7 deletions

View file

@ -458,7 +458,7 @@ void server_deinit(server_t *server)
worker_pool_destroy(server->workers);
/* Free zone database. */
knot_zonedb_deep_free(&server->zone_db);
knot_zonedb_deep_free(&server->zone_db, true);
/* Free remaining events. */
evsched_deinit(&server->sched);

View file

@ -317,7 +317,7 @@ static void remove_old_zonedb(conf_t *conf, knot_zonedb_t *db_old,
knot_zonedb_iter_free(it);
if (full) {
knot_zonedb_deep_free(&db_old);
knot_zonedb_deep_free(&db_old, false);
} else {
knot_zonedb_free(&db_old);
}

View file

@ -24,7 +24,7 @@
#include "contrib/ucw/mempool.h"
/*! \brief Discard zone in zone database. */
static void discard_zone(zone_t *zone)
static void discard_zone(zone_t *zone, bool abort_txn)
{
// Don't flush if removed zone (no previous configuration available).
if (conf_rawid_exists(conf(), C_ZONE, zone->name, knot_dname_size(zone->name))) {
@ -39,6 +39,9 @@ static void discard_zone(zone_t *zone)
}
}
if (abort_txn) {
zone_control_clear(zone);
}
zone_free(&zone);
}
@ -155,12 +158,12 @@ void knot_zonedb_free(knot_zonedb_t **db)
*db = NULL;
}
void knot_zonedb_deep_free(knot_zonedb_t **db)
void knot_zonedb_deep_free(knot_zonedb_t **db, bool abort_txn)
{
if (db == NULL || *db == NULL) {
return;
}
knot_zonedb_foreach(*db, discard_zone);
knot_zonedb_foreach(*db, discard_zone, abort_txn);
knot_zonedb_free(db);
}

View file

@ -120,5 +120,6 @@ void knot_zonedb_free(knot_zonedb_t **db);
* \brief Destroys and deallocates the whole zone database including the zones.
*
* \param db Zone database to be destroyed.
* \param abort_txn Indication that possible zone transactions are aborted.
*/
void knot_zonedb_deep_free(knot_zonedb_t **db);
void knot_zonedb_deep_free(knot_zonedb_t **db, bool abort_txn);

View file

@ -0,0 +1,32 @@
#!/usr/bin/env python3
'''Test on server shutdown when a zone transaction is open.'''
import psutil
from dnstest.libknot import libknot
from dnstest.test import Test
from dnstest.utils import *
t = Test()
knot = t.server("knot")
zone = t.zone("example.com.")
t.link(zone, knot)
ctl = libknot.control.KnotCtl()
t.start()
ctl.connect(os.path.join(knot.dir, "knot.sock"))
ctl.send_block(cmd="zone-begin", zone=zone[0].name)
ctl.receive_block()
ctl.send(libknot.control.KnotCtlType.END)
ctl.close()
knot.stop()
t.sleep(1)
if psutil.pid_exists(knot.proc.pid):
set_err("Server still running")
t.end()

View file

@ -110,6 +110,6 @@ int main(int argc, char *argv[])
ok(nr_passed == ZONE_COUNT, "zonedb: removed all zones");
cleanup:
knot_zonedb_deep_free(&db);
knot_zonedb_deep_free(&db, false);
return 0;
}