Annotation of embedaddon/ntp/lib/isc/unix/app.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2004, 2005, 2007, 2008  Internet Systems Consortium, Inc. ("ISC")
        !             3:  * Copyright (C) 1999-2003  Internet Software Consortium.
        !             4:  *
        !             5:  * Permission to use, copy, modify, and/or distribute this software for any
        !             6:  * purpose with or without fee is hereby granted, provided that the above
        !             7:  * copyright notice and this permission notice appear in all copies.
        !             8:  *
        !             9:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
        !            10:  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
        !            11:  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
        !            12:  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
        !            13:  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
        !            14:  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
        !            15:  * PERFORMANCE OF THIS SOFTWARE.
        !            16:  */
        !            17: 
        !            18: /* $Id: app.c,v 1.60 2008/10/15 03:41:17 marka Exp $ */
        !            19: 
        !            20: /*! \file */
        !            21: 
        !            22: #include <config.h>
        !            23: 
        !            24: #include <sys/param.h> /* Openserver 5.0.6A and FD_SETSIZE */
        !            25: #include <sys/types.h>
        !            26: 
        !            27: #include <stddef.h>
        !            28: #include <stdlib.h>
        !            29: #include <errno.h>
        !            30: #include <unistd.h>
        !            31: #include <signal.h>
        !            32: #include <sys/time.h>
        !            33: #ifdef HAVE_EPOLL
        !            34: #include <sys/epoll.h>
        !            35: #endif
        !            36: 
        !            37: #include <isc/app.h>
        !            38: #include <isc/boolean.h>
        !            39: #include <isc/condition.h>
        !            40: #include <isc/msgs.h>
        !            41: #include <isc/mutex.h>
        !            42: #include <isc/event.h>
        !            43: #include <isc/platform.h>
        !            44: #include <isc/strerror.h>
        !            45: #include <isc/string.h>
        !            46: #include <isc/task.h>
        !            47: #include <isc/time.h>
        !            48: #include <isc/util.h>
        !            49: 
        !            50: #ifdef ISC_PLATFORM_USETHREADS
        !            51: #include <pthread.h>
        !            52: #else /* ISC_PLATFORM_USETHREADS */
        !            53: #include "../timer_p.h"
        !            54: #include "../task_p.h"
        !            55: #include "socket_p.h"
        !            56: #endif /* ISC_PLATFORM_USETHREADS */
        !            57: 
        !            58: static isc_eventlist_t         on_run;
        !            59: static isc_mutex_t             lock;
        !            60: static isc_boolean_t           shutdown_requested = ISC_FALSE;
        !            61: static isc_boolean_t           running = ISC_FALSE;
        !            62: /*!
        !            63:  * We assume that 'want_shutdown' can be read and written atomically.
        !            64:  */
        !            65: static volatile isc_boolean_t  want_shutdown = ISC_FALSE;
        !            66: /*
        !            67:  * We assume that 'want_reload' can be read and written atomically.
        !            68:  */
        !            69: static volatile isc_boolean_t  want_reload = ISC_FALSE;
        !            70: 
        !            71: static isc_boolean_t           blocked  = ISC_FALSE;
        !            72: #ifdef ISC_PLATFORM_USETHREADS
        !            73: static pthread_t               blockedthread;
        !            74: #endif /* ISC_PLATFORM_USETHREADS */
        !            75: 
        !            76: #ifdef HAVE_LINUXTHREADS
        !            77: /*!
        !            78:  * Linux has sigwait(), but it appears to prevent signal handlers from
        !            79:  * running, even if they're not in the set being waited for.  This makes
        !            80:  * it impossible to get the default actions for SIGILL, SIGSEGV, etc.
        !            81:  * Instead of messing with it, we just use sigsuspend() instead.
        !            82:  */
        !            83: #undef HAVE_SIGWAIT
        !            84: /*!
        !            85:  * We need to remember which thread is the main thread...
        !            86:  */
        !            87: static pthread_t               main_thread;
        !            88: #endif
        !            89: 
        !            90: #ifndef HAVE_SIGWAIT
        !            91: static void
        !            92: exit_action(int arg) {
        !            93:        UNUSED(arg);
        !            94:        want_shutdown = ISC_TRUE;
        !            95: }
        !            96: 
        !            97: static void
        !            98: reload_action(int arg) {
        !            99:        UNUSED(arg);
        !           100:        want_reload = ISC_TRUE;
        !           101: }
        !           102: #endif
        !           103: 
        !           104: static isc_result_t
        !           105: handle_signal(int sig, void (*handler)(int)) {
        !           106:        struct sigaction sa;
        !           107:        char strbuf[ISC_STRERRORSIZE];
        !           108: 
        !           109:        memset(&sa, 0, sizeof(sa));
        !           110:        sa.sa_handler = handler;
        !           111: 
        !           112:        if (sigfillset(&sa.sa_mask) != 0 ||
        !           113:            sigaction(sig, &sa, NULL) < 0) {
        !           114:                isc__strerror(errno, strbuf, sizeof(strbuf));
        !           115:                UNEXPECTED_ERROR(__FILE__, __LINE__,
        !           116:                                 isc_msgcat_get(isc_msgcat, ISC_MSGSET_APP,
        !           117:                                               ISC_MSG_SIGNALSETUP,
        !           118:                                               "handle_signal() %d setup: %s"),
        !           119:                                 sig, strbuf);
        !           120:                return (ISC_R_UNEXPECTED);
        !           121:        }
        !           122: 
        !           123:        return (ISC_R_SUCCESS);
        !           124: }
        !           125: 
        !           126: isc_result_t
        !           127: isc_app_start(void) {
        !           128:        isc_result_t result;
        !           129:        int presult;
        !           130:        sigset_t sset;
        !           131:        char strbuf[ISC_STRERRORSIZE];
        !           132: 
        !           133:        /*
        !           134:         * Start an ISC library application.
        !           135:         */
        !           136: 
        !           137: #ifdef NEED_PTHREAD_INIT
        !           138:        /*
        !           139:         * BSDI 3.1 seg faults in pthread_sigmask() if we don't do this.
        !           140:         */
        !           141:        presult = pthread_init();
        !           142:        if (presult != 0) {
        !           143:                isc__strerror(presult, strbuf, sizeof(strbuf));
        !           144:                UNEXPECTED_ERROR(__FILE__, __LINE__,
        !           145:                                 "isc_app_start() pthread_init: %s", strbuf);
        !           146:                return (ISC_R_UNEXPECTED);
        !           147:        }
        !           148: #endif
        !           149: 
        !           150: #ifdef HAVE_LINUXTHREADS
        !           151:        main_thread = pthread_self();
        !           152: #endif
        !           153: 
        !           154:        result = isc_mutex_init(&lock);
        !           155:        if (result != ISC_R_SUCCESS)
        !           156:                return (result);
        !           157: 
        !           158: #ifndef HAVE_SIGWAIT
        !           159:        /*
        !           160:         * Install do-nothing handlers for SIGINT and SIGTERM.
        !           161:         *
        !           162:         * We install them now because BSDI 3.1 won't block
        !           163:         * the default actions, regardless of what we do with
        !           164:         * pthread_sigmask().
        !           165:         */
        !           166:        result = handle_signal(SIGINT, exit_action);
        !           167:        if (result != ISC_R_SUCCESS)
        !           168:                return (result);
        !           169:        result = handle_signal(SIGTERM, exit_action);
        !           170:        if (result != ISC_R_SUCCESS)
        !           171:                return (result);
        !           172: #endif
        !           173: 
        !           174:        /*
        !           175:         * Always ignore SIGPIPE.
        !           176:         */
        !           177:        result = handle_signal(SIGPIPE, SIG_IGN);
        !           178:        if (result != ISC_R_SUCCESS)
        !           179:                return (result);
        !           180: 
        !           181:        /*
        !           182:         * On Solaris 2, delivery of a signal whose action is SIG_IGN
        !           183:         * will not cause sigwait() to return. We may have inherited
        !           184:         * unexpected actions for SIGHUP, SIGINT, and SIGTERM from our parent
        !           185:         * process (e.g, Solaris cron).  Set an action of SIG_DFL to make
        !           186:         * sure sigwait() works as expected.  Only do this for SIGTERM and
        !           187:         * SIGINT if we don't have sigwait(), since a different handler is
        !           188:         * installed above.
        !           189:         */
        !           190:        result = handle_signal(SIGHUP, SIG_DFL);
        !           191:        if (result != ISC_R_SUCCESS)
        !           192:                return (result);
        !           193: 
        !           194: #ifdef HAVE_SIGWAIT
        !           195:        result = handle_signal(SIGTERM, SIG_DFL);
        !           196:        if (result != ISC_R_SUCCESS)
        !           197:                return (result);
        !           198:        result = handle_signal(SIGINT, SIG_DFL);
        !           199:        if (result != ISC_R_SUCCESS)
        !           200:                return (result);
        !           201: #endif
        !           202: 
        !           203: #ifdef ISC_PLATFORM_USETHREADS
        !           204:        /*
        !           205:         * Block SIGHUP, SIGINT, SIGTERM.
        !           206:         *
        !           207:         * If isc_app_start() is called from the main thread before any other
        !           208:         * threads have been created, then the pthread_sigmask() call below
        !           209:         * will result in all threads having SIGHUP, SIGINT and SIGTERM
        !           210:         * blocked by default, ensuring that only the thread that calls
        !           211:         * sigwait() for them will get those signals.
        !           212:         */
        !           213:        if (sigemptyset(&sset) != 0 ||
        !           214:            sigaddset(&sset, SIGHUP) != 0 ||
        !           215:            sigaddset(&sset, SIGINT) != 0 ||
        !           216:            sigaddset(&sset, SIGTERM) != 0) {
        !           217:                isc__strerror(errno, strbuf, sizeof(strbuf));
        !           218:                UNEXPECTED_ERROR(__FILE__, __LINE__,
        !           219:                                 "isc_app_start() sigsetops: %s", strbuf);
        !           220:                return (ISC_R_UNEXPECTED);
        !           221:        }
        !           222:        presult = pthread_sigmask(SIG_BLOCK, &sset, NULL);
        !           223:        if (presult != 0) {
        !           224:                isc__strerror(presult, strbuf, sizeof(strbuf));
        !           225:                UNEXPECTED_ERROR(__FILE__, __LINE__,
        !           226:                                 "isc_app_start() pthread_sigmask: %s",
        !           227:                                 strbuf);
        !           228:                return (ISC_R_UNEXPECTED);
        !           229:        }
        !           230: #else /* ISC_PLATFORM_USETHREADS */
        !           231:        /*
        !           232:         * Unblock SIGHUP, SIGINT, SIGTERM.
        !           233:         *
        !           234:         * If we're not using threads, we need to make sure that SIGHUP,
        !           235:         * SIGINT and SIGTERM are not inherited as blocked from the parent
        !           236:         * process.
        !           237:         */
        !           238:        if (sigemptyset(&sset) != 0 ||
        !           239:            sigaddset(&sset, SIGHUP) != 0 ||
        !           240:            sigaddset(&sset, SIGINT) != 0 ||
        !           241:            sigaddset(&sset, SIGTERM) != 0) {
        !           242:                isc__strerror(errno, strbuf, sizeof(strbuf));
        !           243:                UNEXPECTED_ERROR(__FILE__, __LINE__,
        !           244:                                 "isc_app_start() sigsetops: %s", strbuf);
        !           245:                return (ISC_R_UNEXPECTED);
        !           246:        }
        !           247:        presult = sigprocmask(SIG_UNBLOCK, &sset, NULL);
        !           248:        if (presult != 0) {
        !           249:                isc__strerror(presult, strbuf, sizeof(strbuf));
        !           250:                UNEXPECTED_ERROR(__FILE__, __LINE__,
        !           251:                                 "isc_app_start() sigprocmask: %s", strbuf);
        !           252:                return (ISC_R_UNEXPECTED);
        !           253:        }
        !           254: #endif /* ISC_PLATFORM_USETHREADS */
        !           255: 
        !           256:        ISC_LIST_INIT(on_run);
        !           257: 
        !           258:        return (ISC_R_SUCCESS);
        !           259: }
        !           260: 
        !           261: isc_result_t
        !           262: isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
        !           263:              void *arg)
        !           264: {
        !           265:        isc_event_t *event;
        !           266:        isc_task_t *cloned_task = NULL;
        !           267:        isc_result_t result;
        !           268: 
        !           269:        LOCK(&lock);
        !           270: 
        !           271:        if (running) {
        !           272:                result = ISC_R_ALREADYRUNNING;
        !           273:                goto unlock;
        !           274:        }
        !           275: 
        !           276:        /*
        !           277:         * Note that we store the task to which we're going to send the event
        !           278:         * in the event's "sender" field.
        !           279:         */
        !           280:        isc_task_attach(task, &cloned_task);
        !           281:        event = isc_event_allocate(mctx, cloned_task, ISC_APPEVENT_SHUTDOWN,
        !           282:                                   action, arg, sizeof(*event));
        !           283:        if (event == NULL) {
        !           284:                result = ISC_R_NOMEMORY;
        !           285:                goto unlock;
        !           286:        }
        !           287: 
        !           288:        ISC_LIST_APPEND(on_run, event, ev_link);
        !           289: 
        !           290:        result = ISC_R_SUCCESS;
        !           291: 
        !           292:  unlock:
        !           293:        UNLOCK(&lock);
        !           294: 
        !           295:        return (result);
        !           296: }
        !           297: 
        !           298: #ifndef ISC_PLATFORM_USETHREADS
        !           299: /*!
        !           300:  * Event loop for nonthreaded programs.
        !           301:  */
        !           302: static isc_result_t
        !           303: evloop(void) {
        !           304:        isc_result_t result;
        !           305:        while (!want_shutdown) {
        !           306:                int n;
        !           307:                isc_time_t when, now;
        !           308:                struct timeval tv, *tvp;
        !           309:                isc_socketwait_t *swait;
        !           310:                isc_boolean_t readytasks;
        !           311:                isc_boolean_t call_timer_dispatch = ISC_FALSE;
        !           312: 
        !           313:                readytasks = isc__taskmgr_ready();
        !           314:                if (readytasks) {
        !           315:                        tv.tv_sec = 0;
        !           316:                        tv.tv_usec = 0;
        !           317:                        tvp = &tv;
        !           318:                        call_timer_dispatch = ISC_TRUE;
        !           319:                } else {
        !           320:                        result = isc__timermgr_nextevent(&when);
        !           321:                        if (result != ISC_R_SUCCESS)
        !           322:                                tvp = NULL;
        !           323:                        else {
        !           324:                                isc_uint64_t us;
        !           325: 
        !           326:                                TIME_NOW(&now);
        !           327:                                us = isc_time_microdiff(&when, &now);
        !           328:                                if (us == 0)
        !           329:                                        call_timer_dispatch = ISC_TRUE;
        !           330:                                tv.tv_sec = us / 1000000;
        !           331:                                tv.tv_usec = us % 1000000;
        !           332:                                tvp = &tv;
        !           333:                        }
        !           334:                }
        !           335: 
        !           336:                swait = NULL;
        !           337:                n = isc__socketmgr_waitevents(tvp, &swait);
        !           338: 
        !           339:                if (n == 0 || call_timer_dispatch) {
        !           340:                        /*
        !           341:                         * We call isc__timermgr_dispatch() only when
        !           342:                         * necessary, in order to reduce overhead.  If the
        !           343:                         * select() call indicates a timeout, we need the
        !           344:                         * dispatch.  Even if not, if we set the 0-timeout
        !           345:                         * for the select() call, we need to check the timer
        !           346:                         * events.  In the 'readytasks' case, there may be no
        !           347:                         * timeout event actually, but there is no other way
        !           348:                         * to reduce the overhead.
        !           349:                         * Note that we do not have to worry about the case
        !           350:                         * where a new timer is inserted during the select()
        !           351:                         * call, since this loop only runs in the non-thread
        !           352:                         * mode.
        !           353:                         */
        !           354:                        isc__timermgr_dispatch();
        !           355:                }
        !           356:                if (n > 0)
        !           357:                        (void)isc__socketmgr_dispatch(swait);
        !           358:                (void)isc__taskmgr_dispatch();
        !           359: 
        !           360:                if (want_reload) {
        !           361:                        want_reload = ISC_FALSE;
        !           362:                        return (ISC_R_RELOAD);
        !           363:                }
        !           364:        }
        !           365:        return (ISC_R_SUCCESS);
        !           366: }
        !           367: 
        !           368: /*
        !           369:  * This is a gross hack to support waiting for condition
        !           370:  * variables in nonthreaded programs in a limited way;
        !           371:  * see lib/isc/nothreads/include/isc/condition.h.
        !           372:  * We implement isc_condition_wait() by entering the
        !           373:  * event loop recursively until the want_shutdown flag
        !           374:  * is set by isc_condition_signal().
        !           375:  */
        !           376: 
        !           377: /*!
        !           378:  * \brief True if we are currently executing in the recursive
        !           379:  * event loop.
        !           380:  */
        !           381: static isc_boolean_t in_recursive_evloop = ISC_FALSE;
        !           382: 
        !           383: /*!
        !           384:  * \brief True if we are exiting the event loop as the result of
        !           385:  * a call to isc_condition_signal() rather than a shutdown
        !           386:  * or reload.
        !           387:  */
        !           388: static isc_boolean_t signalled = ISC_FALSE;
        !           389: 
        !           390: isc_result_t
        !           391: isc__nothread_wait_hack(isc_condition_t *cp, isc_mutex_t *mp) {
        !           392:        isc_result_t result;
        !           393: 
        !           394:        UNUSED(cp);
        !           395:        UNUSED(mp);
        !           396: 
        !           397:        INSIST(!in_recursive_evloop);
        !           398:        in_recursive_evloop = ISC_TRUE;
        !           399: 
        !           400:        INSIST(*mp == 1); /* Mutex must be locked on entry. */
        !           401:        --*mp;
        !           402: 
        !           403:        result = evloop();
        !           404:        if (result == ISC_R_RELOAD)
        !           405:                want_reload = ISC_TRUE;
        !           406:        if (signalled) {
        !           407:                want_shutdown = ISC_FALSE;
        !           408:                signalled = ISC_FALSE;
        !           409:        }
        !           410: 
        !           411:        ++*mp;
        !           412:        in_recursive_evloop = ISC_FALSE;
        !           413:        return (ISC_R_SUCCESS);
        !           414: }
        !           415: 
        !           416: isc_result_t
        !           417: isc__nothread_signal_hack(isc_condition_t *cp) {
        !           418: 
        !           419:        UNUSED(cp);
        !           420: 
        !           421:        INSIST(in_recursive_evloop);
        !           422: 
        !           423:        want_shutdown = ISC_TRUE;
        !           424:        signalled = ISC_TRUE;
        !           425:        return (ISC_R_SUCCESS);
        !           426: }
        !           427: 
        !           428: #endif /* ISC_PLATFORM_USETHREADS */
        !           429: 
        !           430: isc_result_t
        !           431: isc_app_run(void) {
        !           432:        int result;
        !           433:        isc_event_t *event, *next_event;
        !           434:        isc_task_t *task;
        !           435: #ifdef ISC_PLATFORM_USETHREADS
        !           436:        sigset_t sset;
        !           437:        char strbuf[ISC_STRERRORSIZE];
        !           438: #ifdef HAVE_SIGWAIT
        !           439:        int sig;
        !           440: #endif
        !           441: #endif /* ISC_PLATFORM_USETHREADS */
        !           442: 
        !           443: #ifdef HAVE_LINUXTHREADS
        !           444:        REQUIRE(main_thread == pthread_self());
        !           445: #endif
        !           446: 
        !           447:        LOCK(&lock);
        !           448: 
        !           449:        if (!running) {
        !           450:                running = ISC_TRUE;
        !           451: 
        !           452:                /*
        !           453:                 * Post any on-run events (in FIFO order).
        !           454:                 */
        !           455:                for (event = ISC_LIST_HEAD(on_run);
        !           456:                     event != NULL;
        !           457:                     event = next_event) {
        !           458:                        next_event = ISC_LIST_NEXT(event, ev_link);
        !           459:                        ISC_LIST_UNLINK(on_run, event, ev_link);
        !           460:                        task = event->ev_sender;
        !           461:                        event->ev_sender = NULL;
        !           462:                        isc_task_sendanddetach(&task, &event);
        !           463:                }
        !           464: 
        !           465:        }
        !           466: 
        !           467:        UNLOCK(&lock);
        !           468: 
        !           469: #ifndef HAVE_SIGWAIT
        !           470:        /*
        !           471:         * Catch SIGHUP.
        !           472:         *
        !           473:         * We do this here to ensure that the signal handler is installed
        !           474:         * (i.e. that it wasn't a "one-shot" handler).
        !           475:         */
        !           476:        result = handle_signal(SIGHUP, reload_action);
        !           477:        if (result != ISC_R_SUCCESS)
        !           478:                return (ISC_R_SUCCESS);
        !           479: #endif
        !           480: 
        !           481: #ifdef ISC_PLATFORM_USETHREADS
        !           482:        /*
        !           483:         * There is no danger if isc_app_shutdown() is called before we wait
        !           484:         * for signals.  Signals are blocked, so any such signal will simply
        !           485:         * be made pending and we will get it when we call sigwait().
        !           486:         */
        !           487: 
        !           488:        while (!want_shutdown) {
        !           489: #ifdef HAVE_SIGWAIT
        !           490:                /*
        !           491:                 * Wait for SIGHUP, SIGINT, or SIGTERM.
        !           492:                 */
        !           493:                if (sigemptyset(&sset) != 0 ||
        !           494:                    sigaddset(&sset, SIGHUP) != 0 ||
        !           495:                    sigaddset(&sset, SIGINT) != 0 ||
        !           496:                    sigaddset(&sset, SIGTERM) != 0) {
        !           497:                        isc__strerror(errno, strbuf, sizeof(strbuf));
        !           498:                        UNEXPECTED_ERROR(__FILE__, __LINE__,
        !           499:                                         "isc_app_run() sigsetops: %s", strbuf);
        !           500:                        return (ISC_R_UNEXPECTED);
        !           501:                }
        !           502: 
        !           503: #ifndef HAVE_UNIXWARE_SIGWAIT
        !           504:                result = sigwait(&sset, &sig);
        !           505:                if (result == 0) {
        !           506:                        if (sig == SIGINT ||
        !           507:                            sig == SIGTERM)
        !           508:                                want_shutdown = ISC_TRUE;
        !           509:                        else if (sig == SIGHUP)
        !           510:                                want_reload = ISC_TRUE;
        !           511:                }
        !           512: 
        !           513: #else /* Using UnixWare sigwait semantics. */
        !           514:                sig = sigwait(&sset);
        !           515:                if (sig >= 0) {
        !           516:                        if (sig == SIGINT ||
        !           517:                            sig == SIGTERM)
        !           518:                                want_shutdown = ISC_TRUE;
        !           519:                        else if (sig == SIGHUP)
        !           520:                                want_reload = ISC_TRUE;
        !           521:                }
        !           522: 
        !           523: #endif /* HAVE_UNIXWARE_SIGWAIT */
        !           524: #else  /* Don't have sigwait(). */
        !           525:                /*
        !           526:                 * Listen for all signals.
        !           527:                 */
        !           528:                if (sigemptyset(&sset) != 0) {
        !           529:                        isc__strerror(errno, strbuf, sizeof(strbuf));
        !           530:                        UNEXPECTED_ERROR(__FILE__, __LINE__,
        !           531:                                         "isc_app_run() sigsetops: %s", strbuf);
        !           532:                        return (ISC_R_UNEXPECTED);
        !           533:                }
        !           534:                result = sigsuspend(&sset);
        !           535: #endif /* HAVE_SIGWAIT */
        !           536: 
        !           537:                if (want_reload) {
        !           538:                        want_reload = ISC_FALSE;
        !           539:                        return (ISC_R_RELOAD);
        !           540:                }
        !           541: 
        !           542:                if (want_shutdown && blocked)
        !           543:                        exit(1);
        !           544:        }
        !           545: 
        !           546: #else /* ISC_PLATFORM_USETHREADS */
        !           547: 
        !           548:        (void)isc__taskmgr_dispatch();
        !           549: 
        !           550:        result = evloop();
        !           551:        if (result != ISC_R_SUCCESS)
        !           552:                return (result);
        !           553: 
        !           554: #endif /* ISC_PLATFORM_USETHREADS */
        !           555: 
        !           556:        return (ISC_R_SUCCESS);
        !           557: }
        !           558: 
        !           559: isc_result_t
        !           560: isc_app_shutdown(void) {
        !           561:        isc_boolean_t want_kill = ISC_TRUE;
        !           562:        char strbuf[ISC_STRERRORSIZE];
        !           563: 
        !           564:        LOCK(&lock);
        !           565: 
        !           566:        REQUIRE(running);
        !           567: 
        !           568:        if (shutdown_requested)
        !           569:                want_kill = ISC_FALSE;
        !           570:        else
        !           571:                shutdown_requested = ISC_TRUE;
        !           572: 
        !           573:        UNLOCK(&lock);
        !           574: 
        !           575:        if (want_kill) {
        !           576: #ifdef HAVE_LINUXTHREADS
        !           577:                int result;
        !           578: 
        !           579:                result = pthread_kill(main_thread, SIGTERM);
        !           580:                if (result != 0) {
        !           581:                        isc__strerror(result, strbuf, sizeof(strbuf));
        !           582:                        UNEXPECTED_ERROR(__FILE__, __LINE__,
        !           583:                                         "isc_app_shutdown() pthread_kill: %s",
        !           584:                                         strbuf);
        !           585:                        return (ISC_R_UNEXPECTED);
        !           586:                }
        !           587: #else
        !           588:                if (kill(getpid(), SIGTERM) < 0) {
        !           589:                        isc__strerror(errno, strbuf, sizeof(strbuf));
        !           590:                        UNEXPECTED_ERROR(__FILE__, __LINE__,
        !           591:                                         "isc_app_shutdown() kill: %s", strbuf);
        !           592:                        return (ISC_R_UNEXPECTED);
        !           593:                }
        !           594: #endif
        !           595:        }
        !           596: 
        !           597:        return (ISC_R_SUCCESS);
        !           598: }
        !           599: 
        !           600: isc_result_t
        !           601: isc_app_reload(void) {
        !           602:        isc_boolean_t want_kill = ISC_TRUE;
        !           603:        char strbuf[ISC_STRERRORSIZE];
        !           604: 
        !           605:        LOCK(&lock);
        !           606: 
        !           607:        REQUIRE(running);
        !           608: 
        !           609:        /*
        !           610:         * Don't send the reload signal if we're shutting down.
        !           611:         */
        !           612:        if (shutdown_requested)
        !           613:                want_kill = ISC_FALSE;
        !           614: 
        !           615:        UNLOCK(&lock);
        !           616: 
        !           617:        if (want_kill) {
        !           618: #ifdef HAVE_LINUXTHREADS
        !           619:                int result;
        !           620: 
        !           621:                result = pthread_kill(main_thread, SIGHUP);
        !           622:                if (result != 0) {
        !           623:                        isc__strerror(result, strbuf, sizeof(strbuf));
        !           624:                        UNEXPECTED_ERROR(__FILE__, __LINE__,
        !           625:                                         "isc_app_reload() pthread_kill: %s",
        !           626:                                         strbuf);
        !           627:                        return (ISC_R_UNEXPECTED);
        !           628:                }
        !           629: #else
        !           630:                if (kill(getpid(), SIGHUP) < 0) {
        !           631:                        isc__strerror(errno, strbuf, sizeof(strbuf));
        !           632:                        UNEXPECTED_ERROR(__FILE__, __LINE__,
        !           633:                                         "isc_app_reload() kill: %s", strbuf);
        !           634:                        return (ISC_R_UNEXPECTED);
        !           635:                }
        !           636: #endif
        !           637:        }
        !           638: 
        !           639:        return (ISC_R_SUCCESS);
        !           640: }
        !           641: 
        !           642: void
        !           643: isc_app_finish(void) {
        !           644:        DESTROYLOCK(&lock);
        !           645: }
        !           646: 
        !           647: void
        !           648: isc_app_block(void) {
        !           649: #ifdef ISC_PLATFORM_USETHREADS
        !           650:        sigset_t sset;
        !           651: #endif /* ISC_PLATFORM_USETHREADS */
        !           652:        REQUIRE(running);
        !           653:        REQUIRE(!blocked);
        !           654: 
        !           655:        blocked = ISC_TRUE;
        !           656: #ifdef ISC_PLATFORM_USETHREADS
        !           657:        blockedthread = pthread_self();
        !           658:        RUNTIME_CHECK(sigemptyset(&sset) == 0 &&
        !           659:                      sigaddset(&sset, SIGINT) == 0 &&
        !           660:                      sigaddset(&sset, SIGTERM) == 0);
        !           661:        RUNTIME_CHECK(pthread_sigmask(SIG_UNBLOCK, &sset, NULL) == 0);
        !           662: #endif /* ISC_PLATFORM_USETHREADS */
        !           663: }
        !           664: 
        !           665: void
        !           666: isc_app_unblock(void) {
        !           667: #ifdef ISC_PLATFORM_USETHREADS
        !           668:        sigset_t sset;
        !           669: #endif /* ISC_PLATFORM_USETHREADS */
        !           670: 
        !           671:        REQUIRE(running);
        !           672:        REQUIRE(blocked);
        !           673: 
        !           674:        blocked = ISC_FALSE;
        !           675: 
        !           676: #ifdef ISC_PLATFORM_USETHREADS
        !           677:        REQUIRE(blockedthread == pthread_self());
        !           678: 
        !           679:        RUNTIME_CHECK(sigemptyset(&sset) == 0 &&
        !           680:                      sigaddset(&sset, SIGINT) == 0 &&
        !           681:                      sigaddset(&sset, SIGTERM) == 0);
        !           682:        RUNTIME_CHECK(pthread_sigmask(SIG_BLOCK, &sset, NULL) == 0);
        !           683: #endif /* ISC_PLATFORM_USETHREADS */
        !           684: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>