Annotation of embedaddon/ntp/lib/isc/unix/app.c, revision 1.1.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>