mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
fix: usr: Fix intermittent named crashes during asynchronous zone operations
Asynchronous zone loading and dumping operations occasionally dispatched tasks to the wrong internal event loop. This threading violation triggered internal safety assertions that abruptly terminated named. Strict loop affinity is now enforced for these tasks, ensuring they execute on their designated threads and preventing the crashes. Closes #4882 Merge branch '4882-run-rndc-zone-commands-on-correct-loop' into 'main' See merge request isc-projects/bind9!11655
This commit is contained in:
commit
da6a85dc63
4 changed files with 44 additions and 57 deletions
|
|
@ -45,6 +45,8 @@
|
|||
#include <dns/time.h>
|
||||
#include <dns/ttl.h>
|
||||
|
||||
#include "dns/types.h"
|
||||
|
||||
/*!
|
||||
* Grow the number of dns_rdatalist_t (#RDLSZ) and dns_rdata_t (#RDSZ)
|
||||
* structures by these sizes when we need to.
|
||||
|
|
@ -387,29 +389,8 @@ gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *token, bool eol,
|
|||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
dns_loadctx_attach(dns_loadctx_t *source, dns_loadctx_t **target) {
|
||||
REQUIRE(target != NULL && *target == NULL);
|
||||
REQUIRE(DNS_LCTX_VALID(source));
|
||||
|
||||
isc_refcount_increment(&source->references);
|
||||
|
||||
*target = source;
|
||||
}
|
||||
|
||||
void
|
||||
dns_loadctx_detach(dns_loadctx_t **lctxp) {
|
||||
dns_loadctx_t *lctx;
|
||||
|
||||
REQUIRE(lctxp != NULL);
|
||||
lctx = *lctxp;
|
||||
*lctxp = NULL;
|
||||
REQUIRE(DNS_LCTX_VALID(lctx));
|
||||
|
||||
if (isc_refcount_decrement(&lctx->references) == 1) {
|
||||
loadctx_destroy(lctx);
|
||||
}
|
||||
}
|
||||
ISC_REFCOUNT_DECL(dns_loadctx);
|
||||
ISC_REFCOUNT_IMPL(dns_loadctx, loadctx_destroy);
|
||||
|
||||
static void
|
||||
incctx_destroy(isc_mem_t *mctx, dns_incctx_t *ictx) {
|
||||
|
|
@ -2621,6 +2602,21 @@ load_done(void *arg) {
|
|||
dns_loadctx_detach(&lctx);
|
||||
}
|
||||
|
||||
static void
|
||||
load_enqueue(void *lctx) {
|
||||
isc_work_enqueue(isc_loop(), load, load_done, lctx);
|
||||
}
|
||||
|
||||
static void
|
||||
dns_loadctx_enqueue(isc_loop_t *loop, dns_loadctx_t *lctx) {
|
||||
dns_loadctx_ref(lctx);
|
||||
if (loop == isc_loop()) {
|
||||
load_enqueue(lctx);
|
||||
} else {
|
||||
isc_async_run(loop, load_enqueue, lctx);
|
||||
}
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_master_loadfileasync(const char *master_file, dns_name_t *top,
|
||||
dns_name_t *origin, dns_rdataclass_t zclass,
|
||||
|
|
@ -2649,8 +2645,8 @@ dns_master_loadfileasync(const char *master_file, dns_name_t *top,
|
|||
return result;
|
||||
}
|
||||
|
||||
dns_loadctx_attach(lctx, lctxp);
|
||||
isc_work_enqueue(loop, load, load_done, lctx);
|
||||
dns_loadctx_enqueue(loop, lctx);
|
||||
*lctxp = lctx;
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1354,29 +1354,8 @@ dumpctx_destroy(dns_dumpctx_t *dctx) {
|
|||
isc_mem_putanddetach(&dctx->mctx, dctx, sizeof(*dctx));
|
||||
}
|
||||
|
||||
void
|
||||
dns_dumpctx_attach(dns_dumpctx_t *source, dns_dumpctx_t **target) {
|
||||
REQUIRE(DNS_DCTX_VALID(source));
|
||||
REQUIRE(target != NULL && *target == NULL);
|
||||
|
||||
isc_refcount_increment(&source->references);
|
||||
|
||||
*target = source;
|
||||
}
|
||||
|
||||
void
|
||||
dns_dumpctx_detach(dns_dumpctx_t **dctxp) {
|
||||
dns_dumpctx_t *dctx;
|
||||
|
||||
REQUIRE(dctxp != NULL);
|
||||
dctx = *dctxp;
|
||||
*dctxp = NULL;
|
||||
REQUIRE(DNS_DCTX_VALID(dctx));
|
||||
|
||||
if (isc_refcount_decrement(&dctx->references) == 1) {
|
||||
dumpctx_destroy(dctx);
|
||||
}
|
||||
}
|
||||
ISC_REFCOUNT_DECL(dns_dumpctx);
|
||||
ISC_REFCOUNT_IMPL(dns_dumpctx, dumpctx_destroy);
|
||||
|
||||
isc_result_t
|
||||
dns_dumpctx_serial(dns_dumpctx_t *dctx, uint32_t *serial) {
|
||||
|
|
@ -1728,6 +1707,21 @@ cleanup:
|
|||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
master_dump_enqueue(void *dctx) {
|
||||
isc_work_enqueue(isc_loop(), master_dump_cb, master_dump_done_cb, dctx);
|
||||
}
|
||||
|
||||
static void
|
||||
dns_dumpctx_enqueue(isc_loop_t *loop, dns_dumpctx_t *dctx) {
|
||||
dns_dumpctx_ref(dctx);
|
||||
if (loop == isc_loop()) {
|
||||
master_dump_enqueue(dctx);
|
||||
} else {
|
||||
isc_async_run(loop, master_dump_enqueue, dctx);
|
||||
}
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_master_dumptostreamasync(isc_mem_t *mctx, dns_db_t *db,
|
||||
dns_dbversion_t *version,
|
||||
|
|
@ -1745,8 +1739,8 @@ dns_master_dumptostreamasync(isc_mem_t *mctx, dns_db_t *db,
|
|||
dctx->done = done;
|
||||
dctx->done_arg = done_arg;
|
||||
|
||||
dns_dumpctx_attach(dctx, dctxp);
|
||||
isc_work_enqueue(loop, master_dump_cb, master_dump_done_cb, dctx);
|
||||
dns_dumpctx_enqueue(loop, dctx);
|
||||
*dctxp = dctx;
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
|
@ -1834,8 +1828,8 @@ dns_master_dumpasync(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
|
|||
dctx->file = file;
|
||||
dctx->tmpfile = tempname;
|
||||
|
||||
dns_dumpctx_attach(dctx, dctxp);
|
||||
isc_work_enqueue(loop, master_dump_cb, master_dump_done_cb, dctx);
|
||||
dns_dumpctx_enqueue(loop, dctx);
|
||||
*dctxp = dctx;
|
||||
|
||||
return ISC_R_SUCCESS;
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ isc_work_enqueue(isc_loop_t *loop, isc_work_cb work_cb,
|
|||
int r;
|
||||
|
||||
REQUIRE(VALID_LOOP(loop));
|
||||
REQUIRE(isc_loop() == loop);
|
||||
REQUIRE(work_cb != NULL);
|
||||
REQUIRE(after_work_cb != NULL);
|
||||
|
||||
|
|
|
|||
|
|
@ -54,11 +54,7 @@ after_work_cb(void *arg ISC_ATTR_UNUSED) {
|
|||
|
||||
static void
|
||||
work_enqueue_cb(void *arg ISC_ATTR_UNUSED) {
|
||||
isc_tid_t tid = isc_loopmgr_nloops() - 1;
|
||||
|
||||
isc_loop_t *loop = isc_loop_get(tid);
|
||||
|
||||
isc_work_enqueue(loop, work_cb, after_work_cb, NULL);
|
||||
isc_work_enqueue(isc_loop(), work_cb, after_work_cb, NULL);
|
||||
}
|
||||
|
||||
ISC_RUN_TEST_IMPL(isc_work_enqueue) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue