diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h index 71672cc113..c115b71b8b 100644 --- a/bin/named/include/named/server.h +++ b/bin/named/include/named/server.h @@ -24,6 +24,9 @@ #include +#define NS_EVENTCLASS ISC_EVENTCLASS(0x4E43) +#define NS_EVENT_RELOAD (NS_EVENTCLASS + 0) + /* * Name server state. Better here than in lots of separate global variables. */ @@ -51,6 +54,9 @@ struct ns_server { isc_rwlock_t viewlock; ns_interfacemgr_t * interfacemgr; dns_db_t * roothints; + + isc_mutex_t reload_event_lock; + isc_event_t * reload_event; }; #define NS_SERVER_MAGIC 0x53564552 /* SVER */ @@ -72,7 +78,12 @@ ns_server_destroy(ns_server_t **serverp); */ void -ns_server_fatal(isc_logmodule_t *module, isc_boolean_t want_core, - const char *format, ...); +ns_server_reloadwanted(ns_server_t *server); +/* + * Inform a server that a reload is wanted. This function + * may be called asynchronously, from outside the server's task. + * If a reload is already scheduled or in progress, the call + * is ignored. + */ #endif /* NS_SERVER_H */ diff --git a/bin/named/main.c b/bin/named/main.c index 809bf30407..fc3ceda675 100644 --- a/bin/named/main.c +++ b/bin/named/main.c @@ -291,10 +291,7 @@ main(int argc, char *argv[]) { result = isc_app_run(); if (result == ISC_R_RELOAD) { - /* - * XXXRTH Replace this with something useful. - */ - printf("reload requested\n"); + ns_server_reloadwanted(ns_g_server); } else if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_app_run(): %s", diff --git a/bin/named/server.c b/bin/named/server.c index a87f509278..be5bcba4ee 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -97,6 +97,7 @@ typedef struct { } ns_load_t; static void fatal(char *msg, isc_result_t result); +static void ns_server_reload(isc_task_t *task, isc_event_t *event); /* * Configure 'view' according to 'cctx'. @@ -717,6 +718,18 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) { CHECKFATAL(dns_rootns_create(mctx, &server->roothints), "setting up root hints"); + + CHECKFATAL(isc_mutex_init(&server->reload_event_lock), + "initializing reload event lock"); + server->reload_event = + isc_event_allocate(ns_g_mctx, server, + NS_EVENT_RELOAD, + ns_server_reload, + server, + sizeof(isc_event_t)); + CHECKFATAL(server->reload_event == NULL ? + ISC_R_NOMEMORY : ISC_R_SUCCESS, + "allocating reload event"); /* * Setup the server task, which is responsible for coordinating @@ -742,6 +755,8 @@ ns_server_destroy(ns_server_t **serverp) { ns_server_t *server = *serverp; REQUIRE(NS_SERVER_VALID(server)); + isc_event_free(&server->reload_event); + INSIST(ISC_LIST_EMPTY(server->viewlist)); dns_zonemgr_destroy(&server->zonemgr); @@ -775,3 +790,37 @@ fatal(char *msg, isc_result_t result) ISC_LOG_CRITICAL, "exiting (due to fatal error)"); exit(1); } + +static void +ns_server_reload(isc_task_t *task, isc_event_t *event) { + isc_result_t result; + ns_server_t *server = (ns_server_t *) event->arg; + UNUSED(task); + + result = load_configuration(ns_g_conffile, server); + if (result != DNS_R_SUCCESS) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "reloading configuration failed: %s", + isc_result_totext(result)); + } + result = load_zones(server, ISC_FALSE); + if (result != DNS_R_SUCCESS) { + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, + NS_LOGMODULE_SERVER, ISC_LOG_ERROR, + "reloading zones failed: %s", + isc_result_totext(result)); + } + LOCK(&server->reload_event_lock); + INSIST(server->reload_event == NULL); + server->reload_event = event; + UNLOCK(&server->reload_event_lock); +} + +void +ns_server_reloadwanted(ns_server_t *server) { + LOCK(&server->reload_event_lock); + if (server->reload_event != NULL) + isc_task_send(server->task, &server->reload_event); + UNLOCK(&server->reload_event_lock); +}