00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <sys/param.h>
00023 #include <sys/types.h>
00024
00025 #include <stddef.h>
00026 #include <stdlib.h>
00027 #include <errno.h>
00028 #include <unistd.h>
00029 #include <signal.h>
00030 #include <sys/time.h>
00031 #ifdef HAVE_EPOLL
00032 #include <sys/epoll.h>
00033 #endif
00034
00035 #include <isc/app.h>
00036 #include <isc/boolean.h>
00037 #include <isc/condition.h>
00038 #include <isc/mem.h>
00039 #include <isc/msgs.h>
00040 #include <isc/mutex.h>
00041 #include <isc/event.h>
00042 #include <isc/platform.h>
00043 #include <isc/strerror.h>
00044 #include <isc/string.h>
00045 #include <isc/task.h>
00046 #include <isc/time.h>
00047 #include <isc/util.h>
00048
00049 #ifdef ISC_PLATFORM_USETHREADS
00050 #include <pthread.h>
00051 #endif
00052
00053
00054
00055
00056
00057
00058
00059 #ifndef ISC_PLATFORM_USETHREADS
00060 #include "../timer_p.h"
00061 #include "../task_p.h"
00062 #include "socket_p.h"
00063 #endif
00064
00065 #ifdef ISC_PLATFORM_USETHREADS
00066 static pthread_t blockedthread;
00067 #endif
00068
00069
00070
00071
00072
00073
00074 isc_result_t isc__app_start(void);
00075 isc_result_t isc__app_ctxstart(isc_appctx_t *ctx);
00076 isc_result_t isc__app_onrun(isc_mem_t *mctx, isc_task_t *task,
00077 isc_taskaction_t action, void *arg);
00078 isc_result_t isc__app_ctxrun(isc_appctx_t *ctx);
00079 isc_result_t isc__app_run(void);
00080 isc_result_t isc__app_ctxshutdown(isc_appctx_t *ctx);
00081 isc_result_t isc__app_shutdown(void);
00082 isc_result_t isc__app_reload(void);
00083 isc_result_t isc__app_ctxsuspend(isc_appctx_t *ctx);
00084 void isc__app_ctxfinish(isc_appctx_t *ctx);
00085 void isc__app_finish(void);
00086 void isc__app_block(void);
00087 void isc__app_unblock(void);
00088 isc_result_t isc__appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp);
00089 void isc__appctx_destroy(isc_appctx_t **ctxp);
00090 void isc__appctx_settaskmgr(isc_appctx_t *ctx, isc_taskmgr_t *taskmgr);
00091 void isc__appctx_setsocketmgr(isc_appctx_t *ctx, isc_socketmgr_t *socketmgr);
00092 void isc__appctx_settimermgr(isc_appctx_t *ctx, isc_timermgr_t *timermgr);
00093 isc_result_t isc__app_ctxonrun(isc_appctx_t *ctx, isc_mem_t *mctx,
00094 isc_task_t *task, isc_taskaction_t action,
00095 void *arg);
00096
00097
00098
00099
00100
00101 #define APPCTX_MAGIC ISC_MAGIC('A', 'p', 'c', 'x')
00102 #define VALID_APPCTX(c) ISC_MAGIC_VALID(c, APPCTX_MAGIC)
00103
00104 typedef struct isc__appctx {
00105 isc_appctx_t common;
00106 isc_mem_t *mctx;
00107 isc_mutex_t lock;
00108 isc_eventlist_t on_run;
00109 isc_boolean_t shutdown_requested;
00110 isc_boolean_t running;
00111
00112
00113
00114
00115 isc_boolean_t want_shutdown;
00116
00117
00118
00119 isc_boolean_t want_reload;
00120
00121 isc_boolean_t blocked;
00122
00123 isc_taskmgr_t *taskmgr;
00124 isc_socketmgr_t *socketmgr;
00125 isc_timermgr_t *timermgr;
00126 #ifdef ISC_PLATFORM_USETHREADS
00127 isc_mutex_t readylock;
00128 isc_condition_t ready;
00129 #endif
00130 } isc__appctx_t;
00131
00132 static isc__appctx_t isc_g_appctx;
00133
00134 static struct {
00135 isc_appmethods_t methods;
00136
00137
00138
00139
00140 void *run, *shutdown, *start, *reload, *finish, *block, *unblock;
00141 } appmethods = {
00142 {
00143 isc__appctx_destroy,
00144 isc__app_ctxstart,
00145 isc__app_ctxrun,
00146 isc__app_ctxsuspend,
00147 isc__app_ctxshutdown,
00148 isc__app_ctxfinish,
00149 isc__appctx_settaskmgr,
00150 isc__appctx_setsocketmgr,
00151 isc__appctx_settimermgr,
00152 isc__app_ctxonrun
00153 },
00154 (void *)isc__app_run,
00155 (void *)isc__app_shutdown,
00156 (void *)isc__app_start,
00157 (void *)isc__app_reload,
00158 (void *)isc__app_finish,
00159 (void *)isc__app_block,
00160 (void *)isc__app_unblock
00161 };
00162
00163 #ifdef HAVE_LINUXTHREADS
00164
00165
00166
00167
00168
00169
00170 #undef HAVE_SIGWAIT
00171
00172
00173
00174 static pthread_t main_thread;
00175 #endif
00176
00177 #ifndef HAVE_SIGWAIT
00178 static void
00179 exit_action(int arg) {
00180 UNUSED(arg);
00181 isc_g_appctx.want_shutdown = ISC_TRUE;
00182 }
00183
00184 static void
00185 reload_action(int arg) {
00186 UNUSED(arg);
00187 isc_g_appctx.want_reload = ISC_TRUE;
00188 }
00189 #endif
00190
00191 static isc_result_t
00192 handle_signal(int sig, void (*handler)(int)) {
00193 struct sigaction sa;
00194 char strbuf[ISC_STRERRORSIZE];
00195
00196 memset(&sa, 0, sizeof(sa));
00197 sa.sa_handler = handler;
00198
00199 if (sigfillset(&sa.sa_mask) != 0 ||
00200 sigaction(sig, &sa, NULL) < 0) {
00201 isc__strerror(errno, strbuf, sizeof(strbuf));
00202 UNEXPECTED_ERROR(__FILE__, __LINE__,
00203 isc_msgcat_get(isc_msgcat, ISC_MSGSET_APP,
00204 ISC_MSG_SIGNALSETUP,
00205 "handle_signal() %d setup: %s"),
00206 sig, strbuf);
00207 return (ISC_R_UNEXPECTED);
00208 }
00209
00210 return (ISC_R_SUCCESS);
00211 }
00212
00213 isc_result_t
00214 isc__app_ctxstart(isc_appctx_t *ctx0) {
00215 isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
00216 isc_result_t result;
00217 int presult;
00218 sigset_t sset;
00219 char strbuf[ISC_STRERRORSIZE];
00220
00221 REQUIRE(VALID_APPCTX(ctx));
00222
00223
00224
00225
00226
00227 #ifdef NEED_PTHREAD_INIT
00228
00229
00230
00231 presult = pthread_init();
00232 if (presult != 0) {
00233 isc__strerror(presult, strbuf, sizeof(strbuf));
00234 UNEXPECTED_ERROR(__FILE__, __LINE__,
00235 "isc_app_start() pthread_init: %s", strbuf);
00236 return (ISC_R_UNEXPECTED);
00237 }
00238 #endif
00239
00240 #ifdef ISC_PLATFORM_USETHREADS
00241 #ifdef HAVE_LINUXTHREADS
00242 main_thread = pthread_self();
00243 #endif
00244
00245 result = isc_mutex_init(&ctx->readylock);
00246 if (result != ISC_R_SUCCESS)
00247 return (result);
00248
00249 result = isc_condition_init(&ctx->ready);
00250 if (result != ISC_R_SUCCESS)
00251 goto cleanup_rlock;
00252
00253 result = isc_mutex_init(&ctx->lock);
00254 if (result != ISC_R_SUCCESS)
00255 goto cleanup_rcond;
00256 #else
00257 result = isc_mutex_init(&ctx->lock);
00258 if (result != ISC_R_SUCCESS)
00259 goto cleanup;
00260 #endif
00261
00262 ISC_LIST_INIT(ctx->on_run);
00263
00264 ctx->shutdown_requested = ISC_FALSE;
00265 ctx->running = ISC_FALSE;
00266 ctx->want_shutdown = ISC_FALSE;
00267 ctx->want_reload = ISC_FALSE;
00268 ctx->blocked = ISC_FALSE;
00269
00270 #ifndef HAVE_SIGWAIT
00271
00272
00273
00274
00275
00276
00277
00278 result = handle_signal(SIGINT, exit_action);
00279 if (result != ISC_R_SUCCESS)
00280 goto cleanup;
00281 result = handle_signal(SIGTERM, exit_action);
00282 if (result != ISC_R_SUCCESS)
00283 goto cleanup;
00284 #endif
00285
00286
00287
00288
00289 result = handle_signal(SIGPIPE, SIG_IGN);
00290 if (result != ISC_R_SUCCESS)
00291 goto cleanup;
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 result = handle_signal(SIGHUP, SIG_DFL);
00303 if (result != ISC_R_SUCCESS)
00304 goto cleanup;
00305
00306 #ifdef HAVE_SIGWAIT
00307 result = handle_signal(SIGTERM, SIG_DFL);
00308 if (result != ISC_R_SUCCESS)
00309 goto cleanup;
00310 result = handle_signal(SIGINT, SIG_DFL);
00311 if (result != ISC_R_SUCCESS)
00312 goto cleanup;
00313 #endif
00314
00315 #ifdef ISC_PLATFORM_USETHREADS
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 if (sigemptyset(&sset) != 0 ||
00326 sigaddset(&sset, SIGHUP) != 0 ||
00327 sigaddset(&sset, SIGINT) != 0 ||
00328 sigaddset(&sset, SIGTERM) != 0) {
00329 isc__strerror(errno, strbuf, sizeof(strbuf));
00330 UNEXPECTED_ERROR(__FILE__, __LINE__,
00331 "isc_app_start() sigsetops: %s", strbuf);
00332 result = ISC_R_UNEXPECTED;
00333 goto cleanup;
00334 }
00335 presult = pthread_sigmask(SIG_BLOCK, &sset, NULL);
00336 if (presult != 0) {
00337 isc__strerror(presult, strbuf, sizeof(strbuf));
00338 UNEXPECTED_ERROR(__FILE__, __LINE__,
00339 "isc_app_start() pthread_sigmask: %s",
00340 strbuf);
00341 result = ISC_R_UNEXPECTED;
00342 goto cleanup;
00343 }
00344 #else
00345
00346
00347
00348
00349
00350
00351
00352 if (sigemptyset(&sset) != 0 ||
00353 sigaddset(&sset, SIGHUP) != 0 ||
00354 sigaddset(&sset, SIGINT) != 0 ||
00355 sigaddset(&sset, SIGTERM) != 0) {
00356 isc__strerror(errno, strbuf, sizeof(strbuf));
00357 UNEXPECTED_ERROR(__FILE__, __LINE__,
00358 "isc_app_start() sigsetops: %s", strbuf);
00359 result = ISC_R_UNEXPECTED;
00360 goto cleanup;
00361 }
00362 presult = sigprocmask(SIG_UNBLOCK, &sset, NULL);
00363 if (presult != 0) {
00364 isc__strerror(errno, strbuf, sizeof(strbuf));
00365 UNEXPECTED_ERROR(__FILE__, __LINE__,
00366 "isc_app_start() sigprocmask: %s", strbuf);
00367 result = ISC_R_UNEXPECTED;
00368 goto cleanup;
00369 }
00370 #endif
00371
00372 return (ISC_R_SUCCESS);
00373
00374 cleanup:
00375 #ifdef ISC_PLATFORM_USETHREADS
00376 cleanup_rcond:
00377 (void)isc_condition_destroy(&ctx->ready);
00378
00379 cleanup_rlock:
00380 (void)isc_mutex_destroy(&ctx->readylock);
00381 #endif
00382 return (result);
00383 }
00384
00385 isc_result_t
00386 isc__app_start(void) {
00387 isc_g_appctx.common.impmagic = APPCTX_MAGIC;
00388 isc_g_appctx.common.magic = ISCAPI_APPCTX_MAGIC;
00389 isc_g_appctx.common.methods = &appmethods.methods;
00390 isc_g_appctx.mctx = NULL;
00391
00392
00393 return (isc__app_ctxstart((isc_appctx_t *)&isc_g_appctx));
00394 }
00395
00396 isc_result_t
00397 isc__app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
00398 void *arg)
00399 {
00400 return (isc__app_ctxonrun((isc_appctx_t *)&isc_g_appctx, mctx,
00401 task, action, arg));
00402 }
00403
00404 isc_result_t
00405 isc__app_ctxonrun(isc_appctx_t *ctx0, isc_mem_t *mctx, isc_task_t *task,
00406 isc_taskaction_t action, void *arg)
00407 {
00408 isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
00409 isc_event_t *event;
00410 isc_task_t *cloned_task = NULL;
00411 isc_result_t result;
00412
00413 LOCK(&ctx->lock);
00414
00415 if (ctx->running) {
00416 result = ISC_R_ALREADYRUNNING;
00417 goto unlock;
00418 }
00419
00420
00421
00422
00423
00424 isc_task_attach(task, &cloned_task);
00425 event = isc_event_allocate(mctx, cloned_task, ISC_APPEVENT_SHUTDOWN,
00426 action, arg, sizeof(*event));
00427 if (event == NULL) {
00428 result = ISC_R_NOMEMORY;
00429 goto unlock;
00430 }
00431
00432 ISC_LIST_APPEND(ctx->on_run, event, ev_link);
00433
00434 result = ISC_R_SUCCESS;
00435
00436 unlock:
00437 UNLOCK(&ctx->lock);
00438
00439 return (result);
00440 }
00441
00442 #ifndef ISC_PLATFORM_USETHREADS
00443
00444
00445
00446 static isc_result_t
00447 evloop(isc__appctx_t *ctx) {
00448 isc_result_t result;
00449
00450 while (!ctx->want_shutdown) {
00451 int n;
00452 isc_time_t when, now;
00453 struct timeval tv, *tvp;
00454 isc_socketwait_t *swait;
00455 isc_boolean_t readytasks;
00456 isc_boolean_t call_timer_dispatch = ISC_FALSE;
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 if (ctx->want_reload) {
00467 ctx->want_reload = ISC_FALSE;
00468 return (ISC_R_RELOAD);
00469 }
00470
00471 readytasks = isc__taskmgr_ready(ctx->taskmgr);
00472 if (readytasks) {
00473 tv.tv_sec = 0;
00474 tv.tv_usec = 0;
00475 tvp = &tv;
00476 call_timer_dispatch = ISC_TRUE;
00477 } else {
00478 result = isc__timermgr_nextevent(ctx->timermgr, &when);
00479 if (result != ISC_R_SUCCESS)
00480 tvp = NULL;
00481 else {
00482 isc_uint64_t us;
00483
00484 TIME_NOW(&now);
00485 us = isc_time_microdiff(&when, &now);
00486 if (us == 0)
00487 call_timer_dispatch = ISC_TRUE;
00488 tv.tv_sec = us / 1000000;
00489 tv.tv_usec = us % 1000000;
00490 tvp = &tv;
00491 }
00492 }
00493
00494 swait = NULL;
00495 n = isc__socketmgr_waitevents(ctx->socketmgr, tvp, &swait);
00496
00497 if (n == 0 || call_timer_dispatch) {
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 isc__timermgr_dispatch(ctx->timermgr);
00513 }
00514 if (n > 0)
00515 (void)isc__socketmgr_dispatch(ctx->socketmgr, swait);
00516 (void)isc__taskmgr_dispatch(ctx->taskmgr);
00517 }
00518 return (ISC_R_SUCCESS);
00519 }
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 static isc_boolean_t in_recursive_evloop = ISC_FALSE;
00535
00536
00537
00538
00539
00540
00541 static isc_boolean_t signalled = ISC_FALSE;
00542
00543 isc_result_t
00544 isc__nothread_wait_hack(isc_condition_t *cp, isc_mutex_t *mp) {
00545 isc_result_t result;
00546
00547 UNUSED(cp);
00548 UNUSED(mp);
00549
00550 INSIST(!in_recursive_evloop);
00551 in_recursive_evloop = ISC_TRUE;
00552
00553 INSIST(*mp == 1);
00554 --*mp;
00555
00556 result = evloop(&isc_g_appctx);
00557 if (result == ISC_R_RELOAD)
00558 isc_g_appctx.want_reload = ISC_TRUE;
00559 if (signalled) {
00560 isc_g_appctx.want_shutdown = ISC_FALSE;
00561 signalled = ISC_FALSE;
00562 }
00563
00564 ++*mp;
00565 in_recursive_evloop = ISC_FALSE;
00566 return (ISC_R_SUCCESS);
00567 }
00568
00569 isc_result_t
00570 isc__nothread_signal_hack(isc_condition_t *cp) {
00571
00572 UNUSED(cp);
00573
00574 INSIST(in_recursive_evloop);
00575
00576 isc_g_appctx.want_shutdown = ISC_TRUE;
00577 signalled = ISC_TRUE;
00578 return (ISC_R_SUCCESS);
00579 }
00580 #endif
00581
00582 isc_result_t
00583 isc__app_ctxrun(isc_appctx_t *ctx0) {
00584 isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
00585 int result;
00586 isc_event_t *event, *next_event;
00587 isc_task_t *task;
00588 #ifdef ISC_PLATFORM_USETHREADS
00589 sigset_t sset;
00590 char strbuf[ISC_STRERRORSIZE];
00591 #ifdef HAVE_SIGWAIT
00592 int sig;
00593 #endif
00594 #endif
00595
00596 REQUIRE(VALID_APPCTX(ctx));
00597
00598 #ifdef HAVE_LINUXTHREADS
00599 REQUIRE(main_thread == pthread_self());
00600 #endif
00601
00602 LOCK(&ctx->lock);
00603
00604 if (!ctx->running) {
00605 ctx->running = ISC_TRUE;
00606
00607
00608
00609
00610 for (event = ISC_LIST_HEAD(ctx->on_run);
00611 event != NULL;
00612 event = next_event) {
00613 next_event = ISC_LIST_NEXT(event, ev_link);
00614 ISC_LIST_UNLINK(ctx->on_run, event, ev_link);
00615 task = event->ev_sender;
00616 event->ev_sender = NULL;
00617 isc_task_sendanddetach(&task, &event);
00618 }
00619
00620 }
00621
00622 UNLOCK(&ctx->lock);
00623
00624 #ifndef ISC_PLATFORM_USETHREADS
00625 if (isc_bind9 && ctx == &isc_g_appctx) {
00626 result = handle_signal(SIGHUP, reload_action);
00627 if (result != ISC_R_SUCCESS)
00628 return (ISC_R_SUCCESS);
00629 }
00630
00631 (void) isc__taskmgr_dispatch(ctx->taskmgr);
00632 result = evloop(ctx);
00633 return (result);
00634 #else
00635
00636
00637
00638
00639 if (isc_bind9 && ctx != &isc_g_appctx)
00640 return (ISC_R_SUCCESS);
00641
00642
00643
00644
00645
00646
00647
00648 while (!ctx->want_shutdown) {
00649 #ifdef HAVE_SIGWAIT
00650 if (isc_bind9) {
00651
00652
00653
00654
00655 if (sigemptyset(&sset) != 0 ||
00656 sigaddset(&sset, SIGHUP) != 0 ||
00657 sigaddset(&sset, SIGINT) != 0 ||
00658 sigaddset(&sset, SIGTERM) != 0) {
00659 isc__strerror(errno, strbuf, sizeof(strbuf));
00660 UNEXPECTED_ERROR(__FILE__, __LINE__,
00661 "isc_app_run() sigsetops: %s",
00662 strbuf);
00663 return (ISC_R_UNEXPECTED);
00664 }
00665
00666 #ifndef HAVE_UNIXWARE_SIGWAIT
00667 result = sigwait(&sset, &sig);
00668 if (result == 0) {
00669 if (sig == SIGINT || sig == SIGTERM)
00670 ctx->want_shutdown = ISC_TRUE;
00671 else if (sig == SIGHUP)
00672 ctx->want_reload = ISC_TRUE;
00673 }
00674
00675 #else
00676 sig = sigwait(&sset);
00677 if (sig >= 0) {
00678 if (sig == SIGINT || sig == SIGTERM)
00679 ctx->want_shutdown = ISC_TRUE;
00680 else if (sig == SIGHUP)
00681 ctx->want_reload = ISC_TRUE;
00682 }
00683 #endif
00684 } else {
00685
00686
00687
00688
00689 LOCK(&ctx->readylock);
00690 if (ctx->want_shutdown) {
00691
00692 UNLOCK(&ctx->readylock);
00693 break;
00694 }
00695 if (!ctx->want_reload)
00696 WAIT(&ctx->ready, &ctx->readylock);
00697 UNLOCK(&ctx->readylock);
00698 }
00699 #else
00700 if (isc_bind9) {
00701
00702
00703
00704
00705
00706 result = handle_signal(SIGHUP, reload_action);
00707 if (result != ISC_R_SUCCESS)
00708 return (ISC_R_SUCCESS);
00709
00710 if (sigemptyset(&sset) != 0) {
00711 isc__strerror(errno, strbuf, sizeof(strbuf));
00712 UNEXPECTED_ERROR(__FILE__, __LINE__,
00713 "isc_app_run() sigsetops: %s",
00714 strbuf);
00715 return (ISC_R_UNEXPECTED);
00716 }
00717 #ifdef HAVE_GPERFTOOLS_PROFILER
00718 if (sigaddset(&sset, SIGALRM) != 0) {
00719 isc__strerror(errno, strbuf, sizeof(strbuf));
00720 UNEXPECTED_ERROR(__FILE__, __LINE__,
00721 "isc_app_run() sigsetops: %s",
00722 strbuf);
00723 return (ISC_R_UNEXPECTED);
00724 }
00725 #endif
00726 result = sigsuspend(&sset);
00727 } else {
00728
00729
00730
00731
00732 LOCK(&ctx->readylock);
00733 if (ctx->want_shutdown) {
00734
00735 UNLOCK(&ctx->readylock);
00736 break;
00737 }
00738 if (!ctx->want_reload)
00739 WAIT(&ctx->ready, &ctx->readylock);
00740 UNLOCK(&ctx->readylock);
00741 }
00742 #endif
00743
00744 if (ctx->want_reload) {
00745 ctx->want_reload = ISC_FALSE;
00746 return (ISC_R_RELOAD);
00747 }
00748
00749 if (ctx->want_shutdown && ctx->blocked)
00750 exit(1);
00751 }
00752
00753 return (ISC_R_SUCCESS);
00754 #endif
00755 }
00756
00757 isc_result_t
00758 isc__app_run(void) {
00759 return (isc__app_ctxrun((isc_appctx_t *)&isc_g_appctx));
00760 }
00761
00762 isc_result_t
00763 isc__app_ctxshutdown(isc_appctx_t *ctx0) {
00764 isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
00765 isc_boolean_t want_kill = ISC_TRUE;
00766 #ifdef ISC_PLATFORM_USETHREADS
00767 char strbuf[ISC_STRERRORSIZE];
00768 #endif
00769
00770 REQUIRE(VALID_APPCTX(ctx));
00771
00772 LOCK(&ctx->lock);
00773
00774 REQUIRE(ctx->running);
00775
00776 if (ctx->shutdown_requested)
00777 want_kill = ISC_FALSE;
00778 else
00779 ctx->shutdown_requested = ISC_TRUE;
00780
00781 UNLOCK(&ctx->lock);
00782
00783 if (want_kill) {
00784 if (isc_bind9 && ctx != &isc_g_appctx)
00785
00786 ctx->want_shutdown = ISC_TRUE;
00787 else {
00788 #ifndef ISC_PLATFORM_USETHREADS
00789 ctx->want_shutdown = ISC_TRUE;
00790 #else
00791 #ifdef HAVE_LINUXTHREADS
00792 if (isc_bind9) {
00793
00794 int result;
00795
00796 result = pthread_kill(main_thread, SIGTERM);
00797 if (result != 0) {
00798 isc__strerror(result,
00799 strbuf, sizeof(strbuf));
00800 UNEXPECTED_ERROR(__FILE__, __LINE__,
00801 "isc_app_shutdown() "
00802 "pthread_kill: %s",
00803 strbuf);
00804 return (ISC_R_UNEXPECTED);
00805 }
00806 }
00807 #else
00808 if (isc_bind9) {
00809
00810 if (kill(getpid(), SIGTERM) < 0) {
00811 isc__strerror(errno,
00812 strbuf, sizeof(strbuf));
00813 UNEXPECTED_ERROR(__FILE__, __LINE__,
00814 "isc_app_shutdown() "
00815 "kill: %s", strbuf);
00816 return (ISC_R_UNEXPECTED);
00817 }
00818 }
00819 #endif
00820 else {
00821
00822 LOCK(&ctx->readylock);
00823 ctx->want_shutdown = ISC_TRUE;
00824 UNLOCK(&ctx->readylock);
00825 SIGNAL(&ctx->ready);
00826 }
00827 #endif
00828 }
00829 }
00830
00831 return (ISC_R_SUCCESS);
00832 }
00833
00834 isc_result_t
00835 isc__app_shutdown(void) {
00836 return (isc__app_ctxshutdown((isc_appctx_t *)&isc_g_appctx));
00837 }
00838
00839 isc_result_t
00840 isc__app_ctxsuspend(isc_appctx_t *ctx0) {
00841 isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
00842 isc_boolean_t want_kill = ISC_TRUE;
00843 #ifdef ISC_PLATFORM_USETHREADS
00844 char strbuf[ISC_STRERRORSIZE];
00845 #endif
00846
00847 REQUIRE(VALID_APPCTX(ctx));
00848
00849 LOCK(&ctx->lock);
00850
00851 REQUIRE(ctx->running);
00852
00853
00854
00855
00856 if (ctx->shutdown_requested)
00857 want_kill = ISC_FALSE;
00858
00859 UNLOCK(&ctx->lock);
00860
00861 if (want_kill) {
00862 if (isc_bind9 && ctx != &isc_g_appctx)
00863
00864 ctx->want_reload = ISC_TRUE;
00865 else {
00866 #ifndef ISC_PLATFORM_USETHREADS
00867 ctx->want_reload = ISC_TRUE;
00868 #else
00869 #ifdef HAVE_LINUXTHREADS
00870 if (isc_bind9) {
00871
00872 int result;
00873
00874 result = pthread_kill(main_thread, SIGHUP);
00875 if (result != 0) {
00876 isc__strerror(result,
00877 strbuf, sizeof(strbuf));
00878 UNEXPECTED_ERROR(__FILE__, __LINE__,
00879 "isc_app_reload() "
00880 "pthread_kill: %s",
00881 strbuf);
00882 return (ISC_R_UNEXPECTED);
00883 }
00884 }
00885 #else
00886 if (isc_bind9) {
00887
00888 if (kill(getpid(), SIGHUP) < 0) {
00889 isc__strerror(errno,
00890 strbuf, sizeof(strbuf));
00891 UNEXPECTED_ERROR(__FILE__, __LINE__,
00892 "isc_app_reload() "
00893 "kill: %s", strbuf);
00894 return (ISC_R_UNEXPECTED);
00895 }
00896 }
00897 #endif
00898 else {
00899
00900 LOCK(&ctx->readylock);
00901 ctx->want_reload = ISC_TRUE;
00902 UNLOCK(&ctx->readylock);
00903 SIGNAL(&ctx->ready);
00904 }
00905 #endif
00906 }
00907 }
00908
00909 return (ISC_R_SUCCESS);
00910 }
00911
00912 isc_result_t
00913 isc__app_reload(void) {
00914 return (isc__app_ctxsuspend((isc_appctx_t *)&isc_g_appctx));
00915 }
00916
00917 void
00918 isc__app_ctxfinish(isc_appctx_t *ctx0) {
00919 isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
00920
00921 REQUIRE(VALID_APPCTX(ctx));
00922
00923 DESTROYLOCK(&ctx->lock);
00924 }
00925
00926 void
00927 isc__app_finish(void) {
00928 isc__app_ctxfinish((isc_appctx_t *)&isc_g_appctx);
00929 }
00930
00931 void
00932 isc__app_block(void) {
00933 #ifdef ISC_PLATFORM_USETHREADS
00934 sigset_t sset;
00935 #endif
00936 REQUIRE(isc_g_appctx.running);
00937 REQUIRE(!isc_g_appctx.blocked);
00938
00939 isc_g_appctx.blocked = ISC_TRUE;
00940 #ifdef ISC_PLATFORM_USETHREADS
00941 blockedthread = pthread_self();
00942 RUNTIME_CHECK(sigemptyset(&sset) == 0 &&
00943 sigaddset(&sset, SIGINT) == 0 &&
00944 sigaddset(&sset, SIGTERM) == 0);
00945 RUNTIME_CHECK(pthread_sigmask(SIG_UNBLOCK, &sset, NULL) == 0);
00946 #endif
00947 }
00948
00949 void
00950 isc__app_unblock(void) {
00951 #ifdef ISC_PLATFORM_USETHREADS
00952 sigset_t sset;
00953 #endif
00954
00955 REQUIRE(isc_g_appctx.running);
00956 REQUIRE(isc_g_appctx.blocked);
00957
00958 isc_g_appctx.blocked = ISC_FALSE;
00959
00960 #ifdef ISC_PLATFORM_USETHREADS
00961 REQUIRE(blockedthread == pthread_self());
00962
00963 RUNTIME_CHECK(sigemptyset(&sset) == 0 &&
00964 sigaddset(&sset, SIGINT) == 0 &&
00965 sigaddset(&sset, SIGTERM) == 0);
00966 RUNTIME_CHECK(pthread_sigmask(SIG_BLOCK, &sset, NULL) == 0);
00967 #endif
00968 }
00969
00970 isc_result_t
00971 isc__appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) {
00972 isc__appctx_t *ctx;
00973
00974 REQUIRE(mctx != NULL);
00975 REQUIRE(ctxp != NULL && *ctxp == NULL);
00976
00977 ctx = isc_mem_get(mctx, sizeof(*ctx));
00978 if (ctx == NULL)
00979 return (ISC_R_NOMEMORY);
00980
00981 ctx->common.impmagic = APPCTX_MAGIC;
00982 ctx->common.magic = ISCAPI_APPCTX_MAGIC;
00983 ctx->common.methods = &appmethods.methods;
00984
00985 ctx->mctx = NULL;
00986 isc_mem_attach(mctx, &ctx->mctx);
00987
00988 ctx->taskmgr = NULL;
00989 ctx->socketmgr = NULL;
00990 ctx->timermgr = NULL;
00991
00992 *ctxp = (isc_appctx_t *)ctx;
00993
00994 return (ISC_R_SUCCESS);
00995 }
00996
00997 void
00998 isc__appctx_destroy(isc_appctx_t **ctxp) {
00999 isc__appctx_t *ctx;
01000
01001 REQUIRE(ctxp != NULL);
01002 ctx = (isc__appctx_t *)*ctxp;
01003 REQUIRE(VALID_APPCTX(ctx));
01004
01005 isc_mem_putanddetach(&ctx->mctx, ctx, sizeof(*ctx));
01006
01007 *ctxp = NULL;
01008 }
01009
01010 void
01011 isc__appctx_settaskmgr(isc_appctx_t *ctx0, isc_taskmgr_t *taskmgr) {
01012 isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
01013
01014 REQUIRE(VALID_APPCTX(ctx));
01015
01016 ctx->taskmgr = taskmgr;
01017 }
01018
01019 void
01020 isc__appctx_setsocketmgr(isc_appctx_t *ctx0, isc_socketmgr_t *socketmgr) {
01021 isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
01022
01023 REQUIRE(VALID_APPCTX(ctx));
01024
01025 ctx->socketmgr = socketmgr;
01026 }
01027
01028 void
01029 isc__appctx_settimermgr(isc_appctx_t *ctx0, isc_timermgr_t *timermgr) {
01030 isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
01031
01032 REQUIRE(VALID_APPCTX(ctx));
01033
01034 ctx->timermgr = timermgr;
01035 }
01036
01037 isc_result_t
01038 isc__app_register(void) {
01039 return (isc_app_register(isc__appctx_create));
01040 }
01041
01042 #include "../app_api.c"