2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-04 00:25:29 +00:00

allow normal signal handlers for most signals to execute

This commit is contained in:
Bob Halley
2000-01-25 03:33:55 +00:00
parent 5294500a3d
commit 03dd96d177

View File

@@ -39,19 +39,34 @@ static isc_eventlist_t on_run;
static isc_mutex_t lock; static isc_mutex_t lock;
static isc_boolean_t shutdown_requested = ISC_FALSE; static isc_boolean_t shutdown_requested = ISC_FALSE;
static isc_boolean_t running = ISC_FALSE; static isc_boolean_t running = ISC_FALSE;
/*
* We assume that 'want_shutdown' can be read and written atomically.
*/
static isc_boolean_t want_shutdown = ISC_FALSE;
/* /*
* We assume that 'want_reload' can be read and written atomically. * We assume that 'want_reload' can be read and written atomically.
*/ */
static isc_boolean_t want_reload = ISC_FALSE; static isc_boolean_t want_reload = ISC_FALSE;
#ifdef HAVE_LINUXTHREADS #ifdef HAVE_LINUXTHREADS
/*
* Linux has sigwait(), but it appears to prevent signal handlers from
* running, even if they're not in the set being waited for. This makes
* it impossible to get the default actions for SIGILL, SIGSEGV, etc.
* Instead of messing with it, we just use sigsuspend() instead.
*/
#undef HAVE_SIGWAIT
/*
* We need to remember which thread is the main thread...
*/
static pthread_t main_thread; static pthread_t main_thread;
#endif #endif
#ifndef HAVE_SIGWAIT #ifndef HAVE_SIGWAIT
static void static void
no_action(int arg) { exit_action(int arg) {
(void)arg; (void)arg;
want_shutdown = ISC_TRUE;
} }
static void static void
@@ -112,16 +127,19 @@ isc_app_start(void) {
#ifndef HAVE_SIGWAIT #ifndef HAVE_SIGWAIT
/* /*
* Install do-nothing handlers for SIGINT and SIGTERM. * Install do-nothing handlers for SIGINT, SIGQUIT, and SIGTERM.
* *
* We install them now because BSDI 3.1 won't block * We install them now because BSDI 3.1 won't block
* the default actions, regardless of what we do with * the default actions, regardless of what we do with
* pthread_sigmask(). * pthread_sigmask().
*/ */
result = handle_signal(SIGINT, no_action); result = handle_signal(SIGINT, exit_action);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
return (result); return (result);
result = handle_signal(SIGTERM, no_action); result = handle_signal(SIGQUIT, exit_action);
if (result != ISC_R_SUCCESS)
return (result);
result = handle_signal(SIGTERM, exit_action);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
return (result); return (result);
#endif #endif
@@ -138,12 +156,14 @@ isc_app_start(void) {
* *
* If isc_app_start() is called from the main thread before any other * If isc_app_start() is called from the main thread before any other
* threads have been created, then the pthread_sigmask() call below * threads have been created, then the pthread_sigmask() call below
* will result in all threads having SIGHUP, SIGINT and SIGTERM * will result in all threads having SIGHUP, SIGINT, SIGQUIT and
* blocked by default. * SIGTERM blocked by default, ensuring that only the thread that
* calls sigwait() for them will get those signals.
*/ */
if (sigemptyset(&sset) != 0 || if (sigemptyset(&sset) != 0 ||
sigaddset(&sset, SIGHUP) != 0 || sigaddset(&sset, SIGHUP) != 0 ||
sigaddset(&sset, SIGINT) != 0 || sigaddset(&sset, SIGINT) != 0 ||
sigaddset(&sset, SIGQUIT) != 0 ||
sigaddset(&sset, SIGTERM) != 0) { sigaddset(&sset, SIGTERM) != 0) {
UNEXPECTED_ERROR(__FILE__, __LINE__, UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_app_start() sigsetops: %s", "isc_app_start() sigsetops: %s",
@@ -262,16 +282,15 @@ isc_app_run(void) {
* be made pending and we will get it when we call sigwait(). * be made pending and we will get it when we call sigwait().
*/ */
while (!want_shutdown) {
#ifdef HAVE_SIGWAIT #ifdef HAVE_SIGWAIT
/* /*
* Wait for SIGHUP, SIGINT, or SIGTERM. * Wait for SIGHUP, SIGINT, or SIGTERM.
*/ */
if (sigemptyset(&sset) != 0 || if (sigemptyset(&sset) != 0 ||
#ifdef HAVE_LINUXTHREADS
sigaddset(&sset, SIGABRT) != 0 ||
#endif
sigaddset(&sset, SIGHUP) != 0 || sigaddset(&sset, SIGHUP) != 0 ||
sigaddset(&sset, SIGINT) != 0 || sigaddset(&sset, SIGINT) != 0 ||
sigaddset(&sset, SIGQUIT) != 0 ||
sigaddset(&sset, SIGTERM) != 0) { sigaddset(&sset, SIGTERM) != 0) {
UNEXPECTED_ERROR(__FILE__, __LINE__, UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_app_run() sigsetops: %s", "isc_app_run() sigsetops: %s",
@@ -279,21 +298,19 @@ isc_app_run(void) {
return (ISC_R_UNEXPECTED); return (ISC_R_UNEXPECTED);
} }
result = sigwait(&sset, &sig); result = sigwait(&sset, &sig);
/* if (result == 0) {
* sigwait() prevents signal handlers from running, so we have if (sig == SIGINT ||
* to check if it was SIGHUP ourselves. sig == SIGQUIT ||
*/ sig == SIGTERM)
if (result == 0 && sig == SIGHUP) want_shutdown = ISC_TRUE;
else if (sig == SIGHUP)
want_reload = ISC_TRUE; want_reload = ISC_TRUE;
}
#else #else
/* /*
* Block all signals except for SIGHUP, SIGINT, and SIGTERM, and then * Listen for all signals.
* wait for one of them to occur.
*/ */
if (sigfillset(&sset) != 0 || if (sigemptyset(&sset) != 0) {
sigdelset(&sset, SIGHUP) != 0 ||
sigdelset(&sset, SIGINT) != 0 ||
sigdelset(&sset, SIGTERM) != 0) {
UNEXPECTED_ERROR(__FILE__, __LINE__, UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_app_run() sigsetops: %s", "isc_app_run() sigsetops: %s",
strerror(errno)); strerror(errno));
@@ -303,14 +320,10 @@ isc_app_run(void) {
#endif #endif
if (want_reload) { 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; want_reload = ISC_FALSE;
return (ISC_R_RELOAD); return (ISC_R_RELOAD);
} }
}
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }