app.c revision 660a209ee4febf8cd6df7c317b363391e65809f4
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * Copyright (C) 1999-2003 Internet Software Consortium.
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * Permission to use, copy, modify, and/or distribute this software for any
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * purpose with or without fee is hereby granted, provided that the above
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * copyright notice and this permission notice appear in all copies.
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * PERFORMANCE OF THIS SOFTWARE.
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews/* $Id: app.c,v 1.56 2008/01/04 23:46:55 tbox Exp $ */
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews#include <sys/param.h> /* Openserver 5.0.6A and FD_SETSIZE */
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews#else /* ISC_PLATFORM_USETHREADS */
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrewsstatic isc_boolean_t shutdown_requested = ISC_FALSE;
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * We assume that 'want_shutdown' can be read and written atomically.
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrewsstatic volatile isc_boolean_t want_shutdown = ISC_FALSE;
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * We assume that 'want_reload' can be read and written atomically.
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrewsstatic volatile isc_boolean_t want_reload = ISC_FALSE;
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * Linux has sigwait(), but it appears to prevent signal handlers from
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * running, even if they're not in the set being waited for. This makes
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * it impossible to get the default actions for SIGILL, SIGSEGV, etc.
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * Instead of messing with it, we just use sigsuspend() instead.
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * We need to remember which thread is the main thread...
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews "handle_signal() %d setup: %s"),
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * Start an ISC library application.
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * BSDI 3.1 seg faults in pthread_sigmask() if we don't do this.
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews isc__strerror(presult, strbuf, sizeof(strbuf));
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * Install do-nothing handlers for SIGINT and SIGTERM.
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * We install them now because BSDI 3.1 won't block
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * the default actions, regardless of what we do with
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * pthread_sigmask().
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * Always ignore SIGPIPE.
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * On Solaris 2, delivery of a signal whose action is SIG_IGN
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * will not cause sigwait() to return. We may have inherited
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * unexpected actions for SIGHUP, SIGINT, and SIGTERM from our parent
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * process (e.g, Solaris cron). Set an action of SIG_DFL to make
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * sure sigwait() works as expected. Only do this for SIGTERM and
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * SIGINT if we don't have sigwait(), since a different handler is
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * installed above.
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * Block SIGHUP, SIGINT, SIGTERM.
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * If isc_app_start() is called from the main thread before any other
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * threads have been created, then the pthread_sigmask() call below
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * will result in all threads having SIGHUP, SIGINT and SIGTERM
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * blocked by default, ensuring that only the thread that calls
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * sigwait() for them will get those signals.
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews presult = pthread_sigmask(SIG_BLOCK, &sset, NULL);
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews isc__strerror(presult, strbuf, sizeof(strbuf));
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews "isc_app_start() pthread_sigmask: %s",
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews#else /* ISC_PLATFORM_USETHREADS */
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * Unblock SIGHUP, SIGINT, SIGTERM.
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * If we're not using threads, we need to make sure that SIGHUP,
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * SIGINT and SIGTERM are not inherited as blocked from the parent
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews presult = sigprocmask(SIG_UNBLOCK, &sset, NULL);
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews isc__strerror(presult, strbuf, sizeof(strbuf));
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrewsisc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * Note that we store the task to which we're going to send the event
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews * in the event's "sender" field.
393fd55d91306e6def3a3d06748eee031f57bd17Mark Andrews event = isc_event_allocate(mctx, cloned_task, ISC_APPEVENT_SHUTDOWN,
return (result);
#ifndef ISC_PLATFORM_USETHREADS
static isc_result_t
evloop() {
while (!want_shutdown) {
int maxfd;
if (readytasks) {
if (us == 0)
if (n == 0 || call_timer_dispatch) {
maxfd);
(void)isc__taskmgr_dispatch();
if (want_reload) {
return (ISC_R_RELOAD);
return (ISC_R_SUCCESS);
--*mp;
if (signalled) {
++*mp;
return (ISC_R_SUCCESS);
return (ISC_R_SUCCESS);
isc_app_run(void) {
int result;
#ifdef ISC_PLATFORM_USETHREADS
#ifdef HAVE_SIGWAIT
int sig;
#ifdef HAVE_LINUXTHREADS
if (!running) {
#ifndef HAVE_SIGWAIT
return (ISC_R_SUCCESS);
#ifdef ISC_PLATFORM_USETHREADS
while (!want_shutdown) {
#ifdef HAVE_SIGWAIT
return (ISC_R_UNEXPECTED);
#ifndef HAVE_UNIXWARE_SIGWAIT
if (result == 0) {
if (sig >= 0) {
return (ISC_R_UNEXPECTED);
if (want_reload) {
return (ISC_R_RELOAD);
(void)isc__taskmgr_dispatch();
return (result);
return (ISC_R_SUCCESS);
isc_app_shutdown(void) {
if (shutdown_requested)
if (want_kill) {
#ifdef HAVE_LINUXTHREADS
int result;
if (result != 0) {
strbuf);
return (ISC_R_UNEXPECTED);
return (ISC_R_UNEXPECTED);
return (ISC_R_SUCCESS);
isc_app_reload(void) {
if (shutdown_requested)
if (want_kill) {
#ifdef HAVE_LINUXTHREADS
int result;
if (result != 0) {
strbuf);
return (ISC_R_UNEXPECTED);
return (ISC_R_UNEXPECTED);
return (ISC_R_SUCCESS);
isc_app_finish(void) {
isc_app_block(void) {
#ifdef ISC_PLATFORM_USETHREADS
#ifdef ISC_PLATFORM_USETHREADS
isc_app_unblock(void) {
#ifdef ISC_PLATFORM_USETHREADS
#ifdef ISC_PLATFORM_USETHREADS