mirror of
https://github.com/isc-projects/bind9.git
synced 2026-04-23 23:28:18 -04:00
reload support
This commit is contained in:
parent
010170f711
commit
97f1a75cf0
2 changed files with 131 additions and 20 deletions
|
|
@ -39,6 +39,10 @@ static isc_eventlist_t on_run;
|
|||
static isc_mutex_t lock;
|
||||
static isc_boolean_t shutdown_requested = ISC_FALSE;
|
||||
static isc_boolean_t running = ISC_FALSE;
|
||||
/*
|
||||
* We assume that 'want_reload' can be read and written atomically.
|
||||
*/
|
||||
static isc_boolean_t want_reload = ISC_FALSE;
|
||||
|
||||
#ifdef HAVE_LINUXTHREADS
|
||||
static pthread_t main_thread;
|
||||
|
|
@ -47,7 +51,13 @@ static pthread_t main_thread;
|
|||
#ifndef HAVE_SIGWAIT
|
||||
static void
|
||||
no_action(int arg) {
|
||||
(void)arg;
|
||||
(void)arg;
|
||||
}
|
||||
|
||||
static void
|
||||
reload_action(int arg) {
|
||||
(void)arg;
|
||||
want_reload = ISC_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -124,14 +134,15 @@ isc_app_start(void) {
|
|||
return (result);
|
||||
|
||||
/*
|
||||
* Block SIGINT and SIGTERM.
|
||||
* Block SIGHUP, SIGINT, SIGTERM.
|
||||
*
|
||||
* If isc_app_start() is called from the main thread before any other
|
||||
* threads have been created, then the pthread_sigmask() call below
|
||||
* will result in all threads having SIGINT and SIGTERM blocked by
|
||||
* default.
|
||||
* will result in all threads having SIGHUP, SIGINT and SIGTERM
|
||||
* blocked by default.
|
||||
*/
|
||||
if (sigemptyset(&sset) != 0 ||
|
||||
sigaddset(&sset, SIGHUP) != 0 ||
|
||||
sigaddset(&sset, SIGINT) != 0 ||
|
||||
sigaddset(&sset, SIGTERM) != 0) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
|
|
@ -213,23 +224,38 @@ isc_app_run(void) {
|
|||
|
||||
LOCK(&lock);
|
||||
|
||||
running = ISC_TRUE;
|
||||
if (!running) {
|
||||
running = ISC_TRUE;
|
||||
|
||||
/*
|
||||
* Post any on-run events (in FIFO order).
|
||||
*/
|
||||
for (event = ISC_LIST_HEAD(on_run);
|
||||
event != NULL;
|
||||
event = next_event) {
|
||||
next_event = ISC_LIST_NEXT(event, link);
|
||||
ISC_LIST_UNLINK(on_run, event, link);
|
||||
task = event->sender;
|
||||
event->sender = (void *)&running;
|
||||
isc_task_sendanddetach(&task, &event);
|
||||
}
|
||||
|
||||
/*
|
||||
* Post any on-run events (in FIFO order).
|
||||
*/
|
||||
for (event = ISC_LIST_HEAD(on_run);
|
||||
event != NULL;
|
||||
event = next_event) {
|
||||
next_event = ISC_LIST_NEXT(event, link);
|
||||
ISC_LIST_UNLINK(on_run, event, link);
|
||||
task = event->sender;
|
||||
event->sender = (void *)&running;
|
||||
isc_task_sendanddetach(&task, &event);
|
||||
}
|
||||
|
||||
|
||||
UNLOCK(&lock);
|
||||
|
||||
#ifndef HAVE_SIGWAIT
|
||||
/*
|
||||
* Catch SIGHUP.
|
||||
*
|
||||
* We do this here to ensure that the signal handler is installed
|
||||
* (i.e. that it wasn't a "one-shot" handler).
|
||||
*/
|
||||
result = handle_signal(SIGHUP, reload_action);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (ISC_R_SUCCESS);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* There is no danger if isc_app_shutdown() is called before we wait
|
||||
* for signals. Signals are blocked, so any such signal will simply
|
||||
|
|
@ -238,12 +264,13 @@ isc_app_run(void) {
|
|||
|
||||
#ifdef HAVE_SIGWAIT
|
||||
/*
|
||||
* Wait for SIGINT or SIGTERM.
|
||||
* Wait for SIGHUP, SIGINT, or SIGTERM.
|
||||
*/
|
||||
if (sigemptyset(&sset) != 0 ||
|
||||
#ifdef HAVE_LINUXTHREADS
|
||||
sigaddset(&sset, SIGABRT) != 0 ||
|
||||
#endif
|
||||
sigaddset(&sset, SIGHUP) != 0 ||
|
||||
sigaddset(&sset, SIGINT) != 0 ||
|
||||
sigaddset(&sset, SIGTERM) != 0) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
|
|
@ -252,12 +279,19 @@ isc_app_run(void) {
|
|||
return (ISC_R_UNEXPECTED);
|
||||
}
|
||||
result = sigwait(&sset, &sig);
|
||||
/*
|
||||
* sigwait() prevents signal handlers from running, so we have
|
||||
* to check if it was SIGHUP ourselves.
|
||||
*/
|
||||
if (result == 0 && sig == SIGHUP)
|
||||
want_reload = ISC_TRUE;
|
||||
#else
|
||||
/*
|
||||
* Block all signals except for SIGINT and SIGTERM, and then
|
||||
* Block all signals except for SIGHUP, SIGINT, and SIGTERM, and then
|
||||
* wait for one of them to occur.
|
||||
*/
|
||||
if (sigfillset(&sset) != 0 ||
|
||||
sigdelset(&sset, SIGHUP) != 0 ||
|
||||
sigdelset(&sset, SIGINT) != 0 ||
|
||||
sigdelset(&sset, SIGTERM) != 0) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
|
|
@ -268,6 +302,16 @@ isc_app_run(void) {
|
|||
result = sigsuspend(&sset);
|
||||
#endif
|
||||
|
||||
if (want_reload) {
|
||||
/*
|
||||
* SIGHUP is blocked now (it's only unblocked when we're
|
||||
* calling sigsuspend()/sigwait()), so there's no race with
|
||||
* the reload_action signal handler when we clear want_reload.
|
||||
*/
|
||||
want_reload = ISC_FALSE;
|
||||
return (ISC_R_RELOAD);
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
|
|
@ -314,6 +358,50 @@ isc_app_shutdown(void) {
|
|||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc_app_reload(void) {
|
||||
isc_boolean_t want_kill = ISC_TRUE;
|
||||
|
||||
/*
|
||||
* Request application reload.
|
||||
*/
|
||||
|
||||
LOCK(&lock);
|
||||
|
||||
REQUIRE(running);
|
||||
|
||||
/*
|
||||
* Don't send the reload signal if we're shutting down.
|
||||
*/
|
||||
if (shutdown_requested)
|
||||
want_kill = ISC_FALSE;
|
||||
|
||||
UNLOCK(&lock);
|
||||
|
||||
if (want_kill) {
|
||||
#ifdef HAVE_LINUXTHREADS
|
||||
int result;
|
||||
|
||||
result = pthread_kill(main_thread, SIGHUP);
|
||||
if (result != 0) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"isc_app_shutdown() pthread_kill: %s",
|
||||
strerror(result));
|
||||
return (ISC_R_UNEXPECTED);
|
||||
}
|
||||
#else
|
||||
if (kill(getpid(), SIGHUP) < 0) {
|
||||
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
||||
"isc_app_shutdown() kill: %s",
|
||||
strerror(errno));
|
||||
return (ISC_R_UNEXPECTED);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
isc_app_finish(void) {
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -44,6 +44,11 @@
|
|||
*
|
||||
* isc_app_finish(); Call very late in main().
|
||||
*
|
||||
* Applications that want to use SIGHUP/isc_app_reload() to trigger reloading
|
||||
* should check the result of isc_app_run() and call the reload routine if
|
||||
* the result is ISC_R_RELOAD. They should then call isc_app_run() again
|
||||
* to resume waiting for reload or termination.
|
||||
*
|
||||
* Use of this module is not required. In particular, isc_app_start() is
|
||||
* NOT an ISC library initialization routine.
|
||||
*
|
||||
|
|
@ -118,6 +123,10 @@ isc_app_run(void);
|
|||
* Ensures:
|
||||
* Any events requested via isc_app_onrun() will have been posted (in
|
||||
* FIFO order) before isc_app_run() blocks.
|
||||
*
|
||||
* Returns:
|
||||
* ISC_R_SUCCESS Shutdown has been requested.
|
||||
* ISC_R_RELOAD Reload has been requested.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
|
|
@ -126,7 +135,21 @@ isc_app_shutdown(void);
|
|||
* Request application shutdown.
|
||||
*
|
||||
* Notes:
|
||||
* It is safe to call isc_app_shutdown() multiple times.
|
||||
* It is safe to call isc_app_shutdown() multiple times. Shutdown will
|
||||
* only be triggered once.
|
||||
*
|
||||
* Requires:
|
||||
* isc_app_run() has been called.
|
||||
*
|
||||
* Returns:
|
||||
* ISC_R_SUCCESS
|
||||
* ISC_R_UNEXPECTED
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_app_reload(void);
|
||||
/*
|
||||
* Request application reload.
|
||||
*
|
||||
* Requires:
|
||||
* isc_app_run() has been called.
|
||||
|
|
|
|||
Loading…
Reference in a new issue