1*00b67f09SDavid van Moolenbroek /* $NetBSD: app.c,v 1.13 2015/07/08 17:28:59 christos Exp $ */
2*00b67f09SDavid van Moolenbroek
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek * Copyright (C) 2004, 2005, 2007-2009, 2013-2015 Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek * Copyright (C) 1999-2003 Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek *
7*00b67f09SDavid van Moolenbroek * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek *
11*00b67f09SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek */
19*00b67f09SDavid van Moolenbroek
20*00b67f09SDavid van Moolenbroek /*! \file */
21*00b67f09SDavid van Moolenbroek
22*00b67f09SDavid van Moolenbroek #include <config.h>
23*00b67f09SDavid van Moolenbroek
24*00b67f09SDavid van Moolenbroek #include <sys/param.h> /* Openserver 5.0.6A and FD_SETSIZE */
25*00b67f09SDavid van Moolenbroek #include <sys/types.h>
26*00b67f09SDavid van Moolenbroek
27*00b67f09SDavid van Moolenbroek #include <stddef.h>
28*00b67f09SDavid van Moolenbroek #include <stdlib.h>
29*00b67f09SDavid van Moolenbroek #include <errno.h>
30*00b67f09SDavid van Moolenbroek #include <unistd.h>
31*00b67f09SDavid van Moolenbroek #include <signal.h>
32*00b67f09SDavid van Moolenbroek #include <sys/time.h>
33*00b67f09SDavid van Moolenbroek #ifdef HAVE_EPOLL
34*00b67f09SDavid van Moolenbroek #include <sys/epoll.h>
35*00b67f09SDavid van Moolenbroek #endif
36*00b67f09SDavid van Moolenbroek
37*00b67f09SDavid van Moolenbroek #include <isc/app.h>
38*00b67f09SDavid van Moolenbroek #include <isc/boolean.h>
39*00b67f09SDavid van Moolenbroek #include <isc/condition.h>
40*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
41*00b67f09SDavid van Moolenbroek #include <isc/msgs.h>
42*00b67f09SDavid van Moolenbroek #include <isc/mutex.h>
43*00b67f09SDavid van Moolenbroek #include <isc/event.h>
44*00b67f09SDavid van Moolenbroek #include <isc/platform.h>
45*00b67f09SDavid van Moolenbroek #include <isc/strerror.h>
46*00b67f09SDavid van Moolenbroek #include <isc/string.h>
47*00b67f09SDavid van Moolenbroek #include <isc/task.h>
48*00b67f09SDavid van Moolenbroek #include <isc/time.h>
49*00b67f09SDavid van Moolenbroek #include <isc/util.h>
50*00b67f09SDavid van Moolenbroek
51*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
52*00b67f09SDavid van Moolenbroek #include <pthread.h>
53*00b67f09SDavid van Moolenbroek #endif
54*00b67f09SDavid van Moolenbroek
55*00b67f09SDavid van Moolenbroek /*%
56*00b67f09SDavid van Moolenbroek * For BIND9 internal applications built with threads, we use a single app
57*00b67f09SDavid van Moolenbroek * context and let multiple worker, I/O, timer threads do actual jobs.
58*00b67f09SDavid van Moolenbroek * For other cases (including BIND9 built without threads) an app context acts
59*00b67f09SDavid van Moolenbroek * as an event loop dispatching various events.
60*00b67f09SDavid van Moolenbroek */
61*00b67f09SDavid van Moolenbroek #ifndef ISC_PLATFORM_USETHREADS
62*00b67f09SDavid van Moolenbroek #include "../timer_p.h"
63*00b67f09SDavid van Moolenbroek #include "../task_p.h"
64*00b67f09SDavid van Moolenbroek #include "socket_p.h"
65*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
66*00b67f09SDavid van Moolenbroek
67*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
68*00b67f09SDavid van Moolenbroek static pthread_t blockedthread;
69*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
70*00b67f09SDavid van Moolenbroek
71*00b67f09SDavid van Moolenbroek /*%
72*00b67f09SDavid van Moolenbroek * The following are intended for internal use (indicated by "isc__"
73*00b67f09SDavid van Moolenbroek * prefix) but are not declared as static, allowing direct access from
74*00b67f09SDavid van Moolenbroek * unit tests etc.
75*00b67f09SDavid van Moolenbroek */
76*00b67f09SDavid van Moolenbroek isc_result_t isc__app_start(void);
77*00b67f09SDavid van Moolenbroek isc_result_t isc__app_ctxstart(isc_appctx_t *ctx);
78*00b67f09SDavid van Moolenbroek isc_result_t isc__app_onrun(isc_mem_t *mctx, isc_task_t *task,
79*00b67f09SDavid van Moolenbroek isc_taskaction_t action, void *arg);
80*00b67f09SDavid van Moolenbroek isc_result_t isc__app_ctxrun(isc_appctx_t *ctx);
81*00b67f09SDavid van Moolenbroek isc_result_t isc__app_run(void);
82*00b67f09SDavid van Moolenbroek isc_result_t isc__app_ctxshutdown(isc_appctx_t *ctx);
83*00b67f09SDavid van Moolenbroek isc_result_t isc__app_shutdown(void);
84*00b67f09SDavid van Moolenbroek isc_result_t isc__app_reload(void);
85*00b67f09SDavid van Moolenbroek isc_result_t isc__app_ctxsuspend(isc_appctx_t *ctx);
86*00b67f09SDavid van Moolenbroek void isc__app_ctxfinish(isc_appctx_t *ctx);
87*00b67f09SDavid van Moolenbroek void isc__app_finish(void);
88*00b67f09SDavid van Moolenbroek void isc__app_block(void);
89*00b67f09SDavid van Moolenbroek void isc__app_unblock(void);
90*00b67f09SDavid van Moolenbroek isc_result_t isc__appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp);
91*00b67f09SDavid van Moolenbroek void isc__appctx_destroy(isc_appctx_t **ctxp);
92*00b67f09SDavid van Moolenbroek void isc__appctx_settaskmgr(isc_appctx_t *ctx, isc_taskmgr_t *taskmgr);
93*00b67f09SDavid van Moolenbroek void isc__appctx_setsocketmgr(isc_appctx_t *ctx, isc_socketmgr_t *socketmgr);
94*00b67f09SDavid van Moolenbroek void isc__appctx_settimermgr(isc_appctx_t *ctx, isc_timermgr_t *timermgr);
95*00b67f09SDavid van Moolenbroek isc_result_t isc__app_ctxonrun(isc_appctx_t *ctx, isc_mem_t *mctx,
96*00b67f09SDavid van Moolenbroek isc_task_t *task, isc_taskaction_t action,
97*00b67f09SDavid van Moolenbroek void *arg);
98*00b67f09SDavid van Moolenbroek
99*00b67f09SDavid van Moolenbroek /*
100*00b67f09SDavid van Moolenbroek * The application context of this module. This implementation actually
101*00b67f09SDavid van Moolenbroek * doesn't use it. (This may change in the future).
102*00b67f09SDavid van Moolenbroek */
103*00b67f09SDavid van Moolenbroek #define APPCTX_MAGIC ISC_MAGIC('A', 'p', 'c', 'x')
104*00b67f09SDavid van Moolenbroek #define VALID_APPCTX(c) ISC_MAGIC_VALID(c, APPCTX_MAGIC)
105*00b67f09SDavid van Moolenbroek
106*00b67f09SDavid van Moolenbroek typedef struct isc__appctx {
107*00b67f09SDavid van Moolenbroek isc_appctx_t common;
108*00b67f09SDavid van Moolenbroek isc_mem_t *mctx;
109*00b67f09SDavid van Moolenbroek isc_mutex_t lock;
110*00b67f09SDavid van Moolenbroek isc_eventlist_t on_run;
111*00b67f09SDavid van Moolenbroek isc_boolean_t shutdown_requested;
112*00b67f09SDavid van Moolenbroek isc_boolean_t running;
113*00b67f09SDavid van Moolenbroek
114*00b67f09SDavid van Moolenbroek /*!
115*00b67f09SDavid van Moolenbroek * We assume that 'want_shutdown' can be read and written atomically.
116*00b67f09SDavid van Moolenbroek */
117*00b67f09SDavid van Moolenbroek isc_boolean_t want_shutdown;
118*00b67f09SDavid van Moolenbroek /*
119*00b67f09SDavid van Moolenbroek * We assume that 'want_reload' can be read and written atomically.
120*00b67f09SDavid van Moolenbroek */
121*00b67f09SDavid van Moolenbroek isc_boolean_t want_reload;
122*00b67f09SDavid van Moolenbroek
123*00b67f09SDavid van Moolenbroek isc_boolean_t blocked;
124*00b67f09SDavid van Moolenbroek
125*00b67f09SDavid van Moolenbroek isc_taskmgr_t *taskmgr;
126*00b67f09SDavid van Moolenbroek isc_socketmgr_t *socketmgr;
127*00b67f09SDavid van Moolenbroek isc_timermgr_t *timermgr;
128*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
129*00b67f09SDavid van Moolenbroek isc_mutex_t readylock;
130*00b67f09SDavid van Moolenbroek isc_condition_t ready;
131*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
132*00b67f09SDavid van Moolenbroek } isc__appctx_t;
133*00b67f09SDavid van Moolenbroek
134*00b67f09SDavid van Moolenbroek static isc__appctx_t isc_g_appctx;
135*00b67f09SDavid van Moolenbroek
136*00b67f09SDavid van Moolenbroek static struct {
137*00b67f09SDavid van Moolenbroek isc_appmethods_t methods;
138*00b67f09SDavid van Moolenbroek
139*00b67f09SDavid van Moolenbroek /*%
140*00b67f09SDavid van Moolenbroek * The following are defined just for avoiding unused static functions.
141*00b67f09SDavid van Moolenbroek */
142*00b67f09SDavid van Moolenbroek void *run, *shutdown, *start, *reload, *finish, *block, *unblock;
143*00b67f09SDavid van Moolenbroek } appmethods = {
144*00b67f09SDavid van Moolenbroek {
145*00b67f09SDavid van Moolenbroek isc__appctx_destroy,
146*00b67f09SDavid van Moolenbroek isc__app_ctxstart,
147*00b67f09SDavid van Moolenbroek isc__app_ctxrun,
148*00b67f09SDavid van Moolenbroek isc__app_ctxsuspend,
149*00b67f09SDavid van Moolenbroek isc__app_ctxshutdown,
150*00b67f09SDavid van Moolenbroek isc__app_ctxfinish,
151*00b67f09SDavid van Moolenbroek isc__appctx_settaskmgr,
152*00b67f09SDavid van Moolenbroek isc__appctx_setsocketmgr,
153*00b67f09SDavid van Moolenbroek isc__appctx_settimermgr,
154*00b67f09SDavid van Moolenbroek isc__app_ctxonrun
155*00b67f09SDavid van Moolenbroek },
156*00b67f09SDavid van Moolenbroek (void *)isc__app_run,
157*00b67f09SDavid van Moolenbroek (void *)isc__app_shutdown,
158*00b67f09SDavid van Moolenbroek (void *)isc__app_start,
159*00b67f09SDavid van Moolenbroek (void *)isc__app_reload,
160*00b67f09SDavid van Moolenbroek (void *)isc__app_finish,
161*00b67f09SDavid van Moolenbroek (void *)isc__app_block,
162*00b67f09SDavid van Moolenbroek (void *)isc__app_unblock
163*00b67f09SDavid van Moolenbroek };
164*00b67f09SDavid van Moolenbroek
165*00b67f09SDavid van Moolenbroek #ifdef HAVE_LINUXTHREADS
166*00b67f09SDavid van Moolenbroek /*!
167*00b67f09SDavid van Moolenbroek * Linux has sigwait(), but it appears to prevent signal handlers from
168*00b67f09SDavid van Moolenbroek * running, even if they're not in the set being waited for. This makes
169*00b67f09SDavid van Moolenbroek * it impossible to get the default actions for SIGILL, SIGSEGV, etc.
170*00b67f09SDavid van Moolenbroek * Instead of messing with it, we just use sigsuspend() instead.
171*00b67f09SDavid van Moolenbroek */
172*00b67f09SDavid van Moolenbroek #undef HAVE_SIGWAIT
173*00b67f09SDavid van Moolenbroek /*!
174*00b67f09SDavid van Moolenbroek * We need to remember which thread is the main thread...
175*00b67f09SDavid van Moolenbroek */
176*00b67f09SDavid van Moolenbroek static pthread_t main_thread;
177*00b67f09SDavid van Moolenbroek #endif
178*00b67f09SDavid van Moolenbroek
179*00b67f09SDavid van Moolenbroek #ifndef HAVE_SIGWAIT
180*00b67f09SDavid van Moolenbroek static void
exit_action(int arg)181*00b67f09SDavid van Moolenbroek exit_action(int arg) {
182*00b67f09SDavid van Moolenbroek UNUSED(arg);
183*00b67f09SDavid van Moolenbroek isc_g_appctx.want_shutdown = ISC_TRUE;
184*00b67f09SDavid van Moolenbroek }
185*00b67f09SDavid van Moolenbroek
186*00b67f09SDavid van Moolenbroek static void
reload_action(int arg)187*00b67f09SDavid van Moolenbroek reload_action(int arg) {
188*00b67f09SDavid van Moolenbroek UNUSED(arg);
189*00b67f09SDavid van Moolenbroek isc_g_appctx.want_reload = ISC_TRUE;
190*00b67f09SDavid van Moolenbroek }
191*00b67f09SDavid van Moolenbroek #endif
192*00b67f09SDavid van Moolenbroek
193*00b67f09SDavid van Moolenbroek static isc_result_t
handle_signal(int sig,void (* handler)(int))194*00b67f09SDavid van Moolenbroek handle_signal(int sig, void (*handler)(int)) {
195*00b67f09SDavid van Moolenbroek struct sigaction sa;
196*00b67f09SDavid van Moolenbroek char strbuf[ISC_STRERRORSIZE];
197*00b67f09SDavid van Moolenbroek
198*00b67f09SDavid van Moolenbroek memset(&sa, 0, sizeof(sa));
199*00b67f09SDavid van Moolenbroek sa.sa_handler = handler;
200*00b67f09SDavid van Moolenbroek
201*00b67f09SDavid van Moolenbroek if (sigfillset(&sa.sa_mask) != 0 ||
202*00b67f09SDavid van Moolenbroek sigaction(sig, &sa, NULL) < 0) {
203*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
204*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
205*00b67f09SDavid van Moolenbroek isc_msgcat_get(isc_msgcat, ISC_MSGSET_APP,
206*00b67f09SDavid van Moolenbroek ISC_MSG_SIGNALSETUP,
207*00b67f09SDavid van Moolenbroek "handle_signal() %d setup: %s"),
208*00b67f09SDavid van Moolenbroek sig, strbuf);
209*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTED);
210*00b67f09SDavid van Moolenbroek }
211*00b67f09SDavid van Moolenbroek
212*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
213*00b67f09SDavid van Moolenbroek }
214*00b67f09SDavid van Moolenbroek
215*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_ctxstart(isc_appctx_t * ctx0)216*00b67f09SDavid van Moolenbroek isc__app_ctxstart(isc_appctx_t *ctx0) {
217*00b67f09SDavid van Moolenbroek isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
218*00b67f09SDavid van Moolenbroek isc_result_t result;
219*00b67f09SDavid van Moolenbroek int presult;
220*00b67f09SDavid van Moolenbroek sigset_t sset;
221*00b67f09SDavid van Moolenbroek char strbuf[ISC_STRERRORSIZE];
222*00b67f09SDavid van Moolenbroek
223*00b67f09SDavid van Moolenbroek REQUIRE(VALID_APPCTX(ctx));
224*00b67f09SDavid van Moolenbroek
225*00b67f09SDavid van Moolenbroek /*
226*00b67f09SDavid van Moolenbroek * Start an ISC library application.
227*00b67f09SDavid van Moolenbroek */
228*00b67f09SDavid van Moolenbroek
229*00b67f09SDavid van Moolenbroek #ifdef NEED_PTHREAD_INIT
230*00b67f09SDavid van Moolenbroek /*
231*00b67f09SDavid van Moolenbroek * BSDI 3.1 seg faults in pthread_sigmask() if we don't do this.
232*00b67f09SDavid van Moolenbroek */
233*00b67f09SDavid van Moolenbroek presult = pthread_init();
234*00b67f09SDavid van Moolenbroek if (presult != 0) {
235*00b67f09SDavid van Moolenbroek isc__strerror(presult, strbuf, sizeof(strbuf));
236*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
237*00b67f09SDavid van Moolenbroek "isc_app_start() pthread_init: %s", strbuf);
238*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTED);
239*00b67f09SDavid van Moolenbroek }
240*00b67f09SDavid van Moolenbroek #endif
241*00b67f09SDavid van Moolenbroek
242*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
243*00b67f09SDavid van Moolenbroek #ifdef HAVE_LINUXTHREADS
244*00b67f09SDavid van Moolenbroek main_thread = pthread_self();
245*00b67f09SDavid van Moolenbroek #endif /* HAVE_LINUXTHREADS */
246*00b67f09SDavid van Moolenbroek
247*00b67f09SDavid van Moolenbroek result = isc_mutex_init(&ctx->readylock);
248*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
249*00b67f09SDavid van Moolenbroek return (result);
250*00b67f09SDavid van Moolenbroek
251*00b67f09SDavid van Moolenbroek result = isc_condition_init(&ctx->ready);
252*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
253*00b67f09SDavid van Moolenbroek goto cleanup_rlock;
254*00b67f09SDavid van Moolenbroek
255*00b67f09SDavid van Moolenbroek result = isc_mutex_init(&ctx->lock);
256*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
257*00b67f09SDavid van Moolenbroek goto cleanup_rcond;
258*00b67f09SDavid van Moolenbroek #else /* ISC_PLATFORM_USETHREADS */
259*00b67f09SDavid van Moolenbroek result = isc_mutex_init(&ctx->lock);
260*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
261*00b67f09SDavid van Moolenbroek goto cleanup;
262*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
263*00b67f09SDavid van Moolenbroek
264*00b67f09SDavid van Moolenbroek ISC_LIST_INIT(ctx->on_run);
265*00b67f09SDavid van Moolenbroek
266*00b67f09SDavid van Moolenbroek ctx->shutdown_requested = ISC_FALSE;
267*00b67f09SDavid van Moolenbroek ctx->running = ISC_FALSE;
268*00b67f09SDavid van Moolenbroek ctx->want_shutdown = ISC_FALSE;
269*00b67f09SDavid van Moolenbroek ctx->want_reload = ISC_FALSE;
270*00b67f09SDavid van Moolenbroek ctx->blocked = ISC_FALSE;
271*00b67f09SDavid van Moolenbroek
272*00b67f09SDavid van Moolenbroek #ifndef HAVE_SIGWAIT
273*00b67f09SDavid van Moolenbroek /*
274*00b67f09SDavid van Moolenbroek * Install do-nothing handlers for SIGINT and SIGTERM.
275*00b67f09SDavid van Moolenbroek *
276*00b67f09SDavid van Moolenbroek * We install them now because BSDI 3.1 won't block
277*00b67f09SDavid van Moolenbroek * the default actions, regardless of what we do with
278*00b67f09SDavid van Moolenbroek * pthread_sigmask().
279*00b67f09SDavid van Moolenbroek */
280*00b67f09SDavid van Moolenbroek result = handle_signal(SIGINT, exit_action);
281*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
282*00b67f09SDavid van Moolenbroek goto cleanup;
283*00b67f09SDavid van Moolenbroek result = handle_signal(SIGTERM, exit_action);
284*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
285*00b67f09SDavid van Moolenbroek goto cleanup;
286*00b67f09SDavid van Moolenbroek #endif
287*00b67f09SDavid van Moolenbroek
288*00b67f09SDavid van Moolenbroek /*
289*00b67f09SDavid van Moolenbroek * Always ignore SIGPIPE.
290*00b67f09SDavid van Moolenbroek */
291*00b67f09SDavid van Moolenbroek result = handle_signal(SIGPIPE, SIG_IGN);
292*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
293*00b67f09SDavid van Moolenbroek goto cleanup;
294*00b67f09SDavid van Moolenbroek
295*00b67f09SDavid van Moolenbroek /*
296*00b67f09SDavid van Moolenbroek * On Solaris 2, delivery of a signal whose action is SIG_IGN
297*00b67f09SDavid van Moolenbroek * will not cause sigwait() to return. We may have inherited
298*00b67f09SDavid van Moolenbroek * unexpected actions for SIGHUP, SIGINT, and SIGTERM from our parent
299*00b67f09SDavid van Moolenbroek * process (e.g, Solaris cron). Set an action of SIG_DFL to make
300*00b67f09SDavid van Moolenbroek * sure sigwait() works as expected. Only do this for SIGTERM and
301*00b67f09SDavid van Moolenbroek * SIGINT if we don't have sigwait(), since a different handler is
302*00b67f09SDavid van Moolenbroek * installed above.
303*00b67f09SDavid van Moolenbroek */
304*00b67f09SDavid van Moolenbroek result = handle_signal(SIGHUP, SIG_DFL);
305*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
306*00b67f09SDavid van Moolenbroek goto cleanup;
307*00b67f09SDavid van Moolenbroek
308*00b67f09SDavid van Moolenbroek #ifdef HAVE_SIGWAIT
309*00b67f09SDavid van Moolenbroek result = handle_signal(SIGTERM, SIG_DFL);
310*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
311*00b67f09SDavid van Moolenbroek goto cleanup;
312*00b67f09SDavid van Moolenbroek result = handle_signal(SIGINT, SIG_DFL);
313*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
314*00b67f09SDavid van Moolenbroek goto cleanup;
315*00b67f09SDavid van Moolenbroek #endif
316*00b67f09SDavid van Moolenbroek
317*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
318*00b67f09SDavid van Moolenbroek if (isc_bind9) {
319*00b67f09SDavid van Moolenbroek /*
320*00b67f09SDavid van Moolenbroek * Block SIGHUP, SIGINT, SIGTERM.
321*00b67f09SDavid van Moolenbroek *
322*00b67f09SDavid van Moolenbroek * If isc_app_start() is called from the main thread before any other
323*00b67f09SDavid van Moolenbroek * threads have been created, then the pthread_sigmask() call below
324*00b67f09SDavid van Moolenbroek * will result in all threads having SIGHUP, SIGINT and SIGTERM
325*00b67f09SDavid van Moolenbroek * blocked by default, ensuring that only the thread that calls
326*00b67f09SDavid van Moolenbroek * sigwait() for them will get those signals.
327*00b67f09SDavid van Moolenbroek */
328*00b67f09SDavid van Moolenbroek if (sigemptyset(&sset) != 0 ||
329*00b67f09SDavid van Moolenbroek sigaddset(&sset, SIGHUP) != 0 ||
330*00b67f09SDavid van Moolenbroek sigaddset(&sset, SIGINT) != 0 ||
331*00b67f09SDavid van Moolenbroek sigaddset(&sset, SIGTERM) != 0) {
332*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
333*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
334*00b67f09SDavid van Moolenbroek "isc_app_start() sigsetops: %s", strbuf);
335*00b67f09SDavid van Moolenbroek result = ISC_R_UNEXPECTED;
336*00b67f09SDavid van Moolenbroek goto cleanup;
337*00b67f09SDavid van Moolenbroek }
338*00b67f09SDavid van Moolenbroek presult = pthread_sigmask(SIG_BLOCK, &sset, NULL);
339*00b67f09SDavid van Moolenbroek if (presult != 0) {
340*00b67f09SDavid van Moolenbroek isc__strerror(presult, strbuf, sizeof(strbuf));
341*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
342*00b67f09SDavid van Moolenbroek "isc_app_start() pthread_sigmask: %s",
343*00b67f09SDavid van Moolenbroek strbuf);
344*00b67f09SDavid van Moolenbroek result = ISC_R_UNEXPECTED;
345*00b67f09SDavid van Moolenbroek goto cleanup;
346*00b67f09SDavid van Moolenbroek }
347*00b67f09SDavid van Moolenbroek }
348*00b67f09SDavid van Moolenbroek #else /* ISC_PLATFORM_USETHREADS */
349*00b67f09SDavid van Moolenbroek /*
350*00b67f09SDavid van Moolenbroek * Unblock SIGHUP, SIGINT, SIGTERM.
351*00b67f09SDavid van Moolenbroek *
352*00b67f09SDavid van Moolenbroek * If we're not using threads, we need to make sure that SIGHUP,
353*00b67f09SDavid van Moolenbroek * SIGINT and SIGTERM are not inherited as blocked from the parent
354*00b67f09SDavid van Moolenbroek * process.
355*00b67f09SDavid van Moolenbroek */
356*00b67f09SDavid van Moolenbroek if (sigemptyset(&sset) != 0 ||
357*00b67f09SDavid van Moolenbroek sigaddset(&sset, SIGHUP) != 0 ||
358*00b67f09SDavid van Moolenbroek sigaddset(&sset, SIGINT) != 0 ||
359*00b67f09SDavid van Moolenbroek sigaddset(&sset, SIGTERM) != 0) {
360*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
361*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
362*00b67f09SDavid van Moolenbroek "isc_app_start() sigsetops: %s", strbuf);
363*00b67f09SDavid van Moolenbroek result = ISC_R_UNEXPECTED;
364*00b67f09SDavid van Moolenbroek goto cleanup;
365*00b67f09SDavid van Moolenbroek }
366*00b67f09SDavid van Moolenbroek presult = sigprocmask(SIG_UNBLOCK, &sset, NULL);
367*00b67f09SDavid van Moolenbroek if (presult != 0) {
368*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
369*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
370*00b67f09SDavid van Moolenbroek "isc_app_start() sigprocmask: %s", strbuf);
371*00b67f09SDavid van Moolenbroek result = ISC_R_UNEXPECTED;
372*00b67f09SDavid van Moolenbroek goto cleanup;
373*00b67f09SDavid van Moolenbroek }
374*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
375*00b67f09SDavid van Moolenbroek
376*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
377*00b67f09SDavid van Moolenbroek
378*00b67f09SDavid van Moolenbroek cleanup:
379*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
380*00b67f09SDavid van Moolenbroek cleanup_rcond:
381*00b67f09SDavid van Moolenbroek (void)isc_condition_destroy(&ctx->ready);
382*00b67f09SDavid van Moolenbroek
383*00b67f09SDavid van Moolenbroek cleanup_rlock:
384*00b67f09SDavid van Moolenbroek (void)isc_mutex_destroy(&ctx->readylock);
385*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
386*00b67f09SDavid van Moolenbroek return (result);
387*00b67f09SDavid van Moolenbroek }
388*00b67f09SDavid van Moolenbroek
389*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_start(void)390*00b67f09SDavid van Moolenbroek isc__app_start(void) {
391*00b67f09SDavid van Moolenbroek isc_g_appctx.common.impmagic = APPCTX_MAGIC;
392*00b67f09SDavid van Moolenbroek isc_g_appctx.common.magic = ISCAPI_APPCTX_MAGIC;
393*00b67f09SDavid van Moolenbroek isc_g_appctx.common.methods = &appmethods.methods;
394*00b67f09SDavid van Moolenbroek isc_g_appctx.mctx = NULL;
395*00b67f09SDavid van Moolenbroek /* The remaining members will be initialized in ctxstart() */
396*00b67f09SDavid van Moolenbroek
397*00b67f09SDavid van Moolenbroek return (isc__app_ctxstart((isc_appctx_t *)&isc_g_appctx));
398*00b67f09SDavid van Moolenbroek }
399*00b67f09SDavid van Moolenbroek
400*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_onrun(isc_mem_t * mctx,isc_task_t * task,isc_taskaction_t action,void * arg)401*00b67f09SDavid van Moolenbroek isc__app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
402*00b67f09SDavid van Moolenbroek void *arg)
403*00b67f09SDavid van Moolenbroek {
404*00b67f09SDavid van Moolenbroek return (isc__app_ctxonrun((isc_appctx_t *)&isc_g_appctx, mctx,
405*00b67f09SDavid van Moolenbroek task, action, arg));
406*00b67f09SDavid van Moolenbroek }
407*00b67f09SDavid van Moolenbroek
408*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_ctxonrun(isc_appctx_t * ctx0,isc_mem_t * mctx,isc_task_t * task,isc_taskaction_t action,void * arg)409*00b67f09SDavid van Moolenbroek isc__app_ctxonrun(isc_appctx_t *ctx0, isc_mem_t *mctx, isc_task_t *task,
410*00b67f09SDavid van Moolenbroek isc_taskaction_t action, void *arg)
411*00b67f09SDavid van Moolenbroek {
412*00b67f09SDavid van Moolenbroek isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
413*00b67f09SDavid van Moolenbroek isc_event_t *event;
414*00b67f09SDavid van Moolenbroek isc_task_t *cloned_task = NULL;
415*00b67f09SDavid van Moolenbroek isc_result_t result;
416*00b67f09SDavid van Moolenbroek
417*00b67f09SDavid van Moolenbroek LOCK(&ctx->lock);
418*00b67f09SDavid van Moolenbroek
419*00b67f09SDavid van Moolenbroek if (ctx->running) {
420*00b67f09SDavid van Moolenbroek result = ISC_R_ALREADYRUNNING;
421*00b67f09SDavid van Moolenbroek goto unlock;
422*00b67f09SDavid van Moolenbroek }
423*00b67f09SDavid van Moolenbroek
424*00b67f09SDavid van Moolenbroek /*
425*00b67f09SDavid van Moolenbroek * Note that we store the task to which we're going to send the event
426*00b67f09SDavid van Moolenbroek * in the event's "sender" field.
427*00b67f09SDavid van Moolenbroek */
428*00b67f09SDavid van Moolenbroek isc_task_attach(task, &cloned_task);
429*00b67f09SDavid van Moolenbroek event = isc_event_allocate(mctx, cloned_task, ISC_APPEVENT_SHUTDOWN,
430*00b67f09SDavid van Moolenbroek action, arg, sizeof(*event));
431*00b67f09SDavid van Moolenbroek if (event == NULL) {
432*00b67f09SDavid van Moolenbroek result = ISC_R_NOMEMORY;
433*00b67f09SDavid van Moolenbroek goto unlock;
434*00b67f09SDavid van Moolenbroek }
435*00b67f09SDavid van Moolenbroek
436*00b67f09SDavid van Moolenbroek ISC_LIST_APPEND(ctx->on_run, event, ev_link);
437*00b67f09SDavid van Moolenbroek
438*00b67f09SDavid van Moolenbroek result = ISC_R_SUCCESS;
439*00b67f09SDavid van Moolenbroek
440*00b67f09SDavid van Moolenbroek unlock:
441*00b67f09SDavid van Moolenbroek UNLOCK(&ctx->lock);
442*00b67f09SDavid van Moolenbroek
443*00b67f09SDavid van Moolenbroek return (result);
444*00b67f09SDavid van Moolenbroek }
445*00b67f09SDavid van Moolenbroek
446*00b67f09SDavid van Moolenbroek #ifndef ISC_PLATFORM_USETHREADS
447*00b67f09SDavid van Moolenbroek /*!
448*00b67f09SDavid van Moolenbroek * Event loop for nonthreaded programs.
449*00b67f09SDavid van Moolenbroek */
450*00b67f09SDavid van Moolenbroek static isc_result_t
evloop(isc__appctx_t * ctx)451*00b67f09SDavid van Moolenbroek evloop(isc__appctx_t *ctx) {
452*00b67f09SDavid van Moolenbroek isc_result_t result;
453*00b67f09SDavid van Moolenbroek
454*00b67f09SDavid van Moolenbroek while (!ctx->want_shutdown) {
455*00b67f09SDavid van Moolenbroek int n;
456*00b67f09SDavid van Moolenbroek isc_time_t when, now;
457*00b67f09SDavid van Moolenbroek struct timeval tv, *tvp;
458*00b67f09SDavid van Moolenbroek isc_socketwait_t *swait;
459*00b67f09SDavid van Moolenbroek isc_boolean_t readytasks;
460*00b67f09SDavid van Moolenbroek isc_boolean_t call_timer_dispatch = ISC_FALSE;
461*00b67f09SDavid van Moolenbroek
462*00b67f09SDavid van Moolenbroek /*
463*00b67f09SDavid van Moolenbroek * Check the reload (or suspend) case first for exiting the
464*00b67f09SDavid van Moolenbroek * loop as fast as possible in case:
465*00b67f09SDavid van Moolenbroek * - the direct call to isc__taskmgr_dispatch() in
466*00b67f09SDavid van Moolenbroek * isc__app_ctxrun() completes all the tasks so far,
467*00b67f09SDavid van Moolenbroek * - there is thus currently no active task, and
468*00b67f09SDavid van Moolenbroek * - there is a timer event
469*00b67f09SDavid van Moolenbroek */
470*00b67f09SDavid van Moolenbroek if (ctx->want_reload) {
471*00b67f09SDavid van Moolenbroek ctx->want_reload = ISC_FALSE;
472*00b67f09SDavid van Moolenbroek return (ISC_R_RELOAD);
473*00b67f09SDavid van Moolenbroek }
474*00b67f09SDavid van Moolenbroek
475*00b67f09SDavid van Moolenbroek readytasks = isc__taskmgr_ready(ctx->taskmgr);
476*00b67f09SDavid van Moolenbroek if (readytasks) {
477*00b67f09SDavid van Moolenbroek tv.tv_sec = 0;
478*00b67f09SDavid van Moolenbroek tv.tv_usec = 0;
479*00b67f09SDavid van Moolenbroek tvp = &tv;
480*00b67f09SDavid van Moolenbroek call_timer_dispatch = ISC_TRUE;
481*00b67f09SDavid van Moolenbroek } else {
482*00b67f09SDavid van Moolenbroek result = isc__timermgr_nextevent(ctx->timermgr, &when);
483*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
484*00b67f09SDavid van Moolenbroek tvp = NULL;
485*00b67f09SDavid van Moolenbroek else {
486*00b67f09SDavid van Moolenbroek isc_uint64_t us;
487*00b67f09SDavid van Moolenbroek
488*00b67f09SDavid van Moolenbroek TIME_NOW(&now);
489*00b67f09SDavid van Moolenbroek us = isc_time_microdiff(&when, &now);
490*00b67f09SDavid van Moolenbroek if (us == 0)
491*00b67f09SDavid van Moolenbroek call_timer_dispatch = ISC_TRUE;
492*00b67f09SDavid van Moolenbroek tv.tv_sec = us / 1000000;
493*00b67f09SDavid van Moolenbroek tv.tv_usec = us % 1000000;
494*00b67f09SDavid van Moolenbroek tvp = &tv;
495*00b67f09SDavid van Moolenbroek }
496*00b67f09SDavid van Moolenbroek }
497*00b67f09SDavid van Moolenbroek
498*00b67f09SDavid van Moolenbroek swait = NULL;
499*00b67f09SDavid van Moolenbroek n = isc__socketmgr_waitevents(ctx->socketmgr, tvp, &swait);
500*00b67f09SDavid van Moolenbroek
501*00b67f09SDavid van Moolenbroek if (n == 0 || call_timer_dispatch) {
502*00b67f09SDavid van Moolenbroek /*
503*00b67f09SDavid van Moolenbroek * We call isc__timermgr_dispatch() only when
504*00b67f09SDavid van Moolenbroek * necessary, in order to reduce overhead. If the
505*00b67f09SDavid van Moolenbroek * select() call indicates a timeout, we need the
506*00b67f09SDavid van Moolenbroek * dispatch. Even if not, if we set the 0-timeout
507*00b67f09SDavid van Moolenbroek * for the select() call, we need to check the timer
508*00b67f09SDavid van Moolenbroek * events. In the 'readytasks' case, there may be no
509*00b67f09SDavid van Moolenbroek * timeout event actually, but there is no other way
510*00b67f09SDavid van Moolenbroek * to reduce the overhead.
511*00b67f09SDavid van Moolenbroek * Note that we do not have to worry about the case
512*00b67f09SDavid van Moolenbroek * where a new timer is inserted during the select()
513*00b67f09SDavid van Moolenbroek * call, since this loop only runs in the non-thread
514*00b67f09SDavid van Moolenbroek * mode.
515*00b67f09SDavid van Moolenbroek */
516*00b67f09SDavid van Moolenbroek isc__timermgr_dispatch(ctx->timermgr);
517*00b67f09SDavid van Moolenbroek }
518*00b67f09SDavid van Moolenbroek if (n > 0)
519*00b67f09SDavid van Moolenbroek (void)isc__socketmgr_dispatch(ctx->socketmgr, swait);
520*00b67f09SDavid van Moolenbroek (void)isc__taskmgr_dispatch(ctx->taskmgr);
521*00b67f09SDavid van Moolenbroek }
522*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
523*00b67f09SDavid van Moolenbroek }
524*00b67f09SDavid van Moolenbroek
525*00b67f09SDavid van Moolenbroek /*
526*00b67f09SDavid van Moolenbroek * This is a gross hack to support waiting for condition
527*00b67f09SDavid van Moolenbroek * variables in nonthreaded programs in a limited way;
528*00b67f09SDavid van Moolenbroek * see lib/isc/nothreads/include/isc/condition.h.
529*00b67f09SDavid van Moolenbroek * We implement isc_condition_wait() by entering the
530*00b67f09SDavid van Moolenbroek * event loop recursively until the want_shutdown flag
531*00b67f09SDavid van Moolenbroek * is set by isc_condition_signal().
532*00b67f09SDavid van Moolenbroek */
533*00b67f09SDavid van Moolenbroek
534*00b67f09SDavid van Moolenbroek /*!
535*00b67f09SDavid van Moolenbroek * \brief True if we are currently executing in the recursive
536*00b67f09SDavid van Moolenbroek * event loop.
537*00b67f09SDavid van Moolenbroek */
538*00b67f09SDavid van Moolenbroek static isc_boolean_t in_recursive_evloop = ISC_FALSE;
539*00b67f09SDavid van Moolenbroek
540*00b67f09SDavid van Moolenbroek /*!
541*00b67f09SDavid van Moolenbroek * \brief True if we are exiting the event loop as the result of
542*00b67f09SDavid van Moolenbroek * a call to isc_condition_signal() rather than a shutdown
543*00b67f09SDavid van Moolenbroek * or reload.
544*00b67f09SDavid van Moolenbroek */
545*00b67f09SDavid van Moolenbroek static isc_boolean_t signalled = ISC_FALSE;
546*00b67f09SDavid van Moolenbroek
547*00b67f09SDavid van Moolenbroek isc_result_t
isc__nothread_wait_hack(isc_condition_t * cp,isc_mutex_t * mp)548*00b67f09SDavid van Moolenbroek isc__nothread_wait_hack(isc_condition_t *cp, isc_mutex_t *mp) {
549*00b67f09SDavid van Moolenbroek isc_result_t result;
550*00b67f09SDavid van Moolenbroek
551*00b67f09SDavid van Moolenbroek UNUSED(cp);
552*00b67f09SDavid van Moolenbroek UNUSED(mp);
553*00b67f09SDavid van Moolenbroek
554*00b67f09SDavid van Moolenbroek INSIST(!in_recursive_evloop);
555*00b67f09SDavid van Moolenbroek in_recursive_evloop = ISC_TRUE;
556*00b67f09SDavid van Moolenbroek
557*00b67f09SDavid van Moolenbroek INSIST(*mp == 1); /* Mutex must be locked on entry. */
558*00b67f09SDavid van Moolenbroek --*mp;
559*00b67f09SDavid van Moolenbroek
560*00b67f09SDavid van Moolenbroek result = evloop(&isc_g_appctx);
561*00b67f09SDavid van Moolenbroek if (result == ISC_R_RELOAD)
562*00b67f09SDavid van Moolenbroek isc_g_appctx.want_reload = ISC_TRUE;
563*00b67f09SDavid van Moolenbroek if (signalled) {
564*00b67f09SDavid van Moolenbroek isc_g_appctx.want_shutdown = ISC_FALSE;
565*00b67f09SDavid van Moolenbroek signalled = ISC_FALSE;
566*00b67f09SDavid van Moolenbroek }
567*00b67f09SDavid van Moolenbroek
568*00b67f09SDavid van Moolenbroek ++*mp;
569*00b67f09SDavid van Moolenbroek in_recursive_evloop = ISC_FALSE;
570*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
571*00b67f09SDavid van Moolenbroek }
572*00b67f09SDavid van Moolenbroek
573*00b67f09SDavid van Moolenbroek isc_result_t
isc__nothread_signal_hack(isc_condition_t * cp)574*00b67f09SDavid van Moolenbroek isc__nothread_signal_hack(isc_condition_t *cp) {
575*00b67f09SDavid van Moolenbroek
576*00b67f09SDavid van Moolenbroek UNUSED(cp);
577*00b67f09SDavid van Moolenbroek
578*00b67f09SDavid van Moolenbroek INSIST(in_recursive_evloop);
579*00b67f09SDavid van Moolenbroek
580*00b67f09SDavid van Moolenbroek isc_g_appctx.want_shutdown = ISC_TRUE;
581*00b67f09SDavid van Moolenbroek signalled = ISC_TRUE;
582*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
583*00b67f09SDavid van Moolenbroek }
584*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
585*00b67f09SDavid van Moolenbroek
586*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_ctxrun(isc_appctx_t * ctx0)587*00b67f09SDavid van Moolenbroek isc__app_ctxrun(isc_appctx_t *ctx0) {
588*00b67f09SDavid van Moolenbroek isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
589*00b67f09SDavid van Moolenbroek int result;
590*00b67f09SDavid van Moolenbroek isc_event_t *event, *next_event;
591*00b67f09SDavid van Moolenbroek isc_task_t *task;
592*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
593*00b67f09SDavid van Moolenbroek sigset_t sset;
594*00b67f09SDavid van Moolenbroek char strbuf[ISC_STRERRORSIZE];
595*00b67f09SDavid van Moolenbroek #ifdef HAVE_SIGWAIT
596*00b67f09SDavid van Moolenbroek int sig;
597*00b67f09SDavid van Moolenbroek #endif /* HAVE_SIGWAIT */
598*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
599*00b67f09SDavid van Moolenbroek
600*00b67f09SDavid van Moolenbroek REQUIRE(VALID_APPCTX(ctx));
601*00b67f09SDavid van Moolenbroek
602*00b67f09SDavid van Moolenbroek #ifdef HAVE_LINUXTHREADS
603*00b67f09SDavid van Moolenbroek REQUIRE(main_thread == pthread_self());
604*00b67f09SDavid van Moolenbroek #endif
605*00b67f09SDavid van Moolenbroek
606*00b67f09SDavid van Moolenbroek LOCK(&ctx->lock);
607*00b67f09SDavid van Moolenbroek
608*00b67f09SDavid van Moolenbroek if (!ctx->running) {
609*00b67f09SDavid van Moolenbroek ctx->running = ISC_TRUE;
610*00b67f09SDavid van Moolenbroek
611*00b67f09SDavid van Moolenbroek /*
612*00b67f09SDavid van Moolenbroek * Post any on-run events (in FIFO order).
613*00b67f09SDavid van Moolenbroek */
614*00b67f09SDavid van Moolenbroek for (event = ISC_LIST_HEAD(ctx->on_run);
615*00b67f09SDavid van Moolenbroek event != NULL;
616*00b67f09SDavid van Moolenbroek event = next_event) {
617*00b67f09SDavid van Moolenbroek next_event = ISC_LIST_NEXT(event, ev_link);
618*00b67f09SDavid van Moolenbroek ISC_LIST_UNLINK(ctx->on_run, event, ev_link);
619*00b67f09SDavid van Moolenbroek task = event->ev_sender;
620*00b67f09SDavid van Moolenbroek event->ev_sender = NULL;
621*00b67f09SDavid van Moolenbroek isc_task_sendanddetach(&task, &event);
622*00b67f09SDavid van Moolenbroek }
623*00b67f09SDavid van Moolenbroek
624*00b67f09SDavid van Moolenbroek }
625*00b67f09SDavid van Moolenbroek
626*00b67f09SDavid van Moolenbroek UNLOCK(&ctx->lock);
627*00b67f09SDavid van Moolenbroek
628*00b67f09SDavid van Moolenbroek #ifndef ISC_PLATFORM_USETHREADS
629*00b67f09SDavid van Moolenbroek if (isc_bind9 && ctx == &isc_g_appctx) {
630*00b67f09SDavid van Moolenbroek result = handle_signal(SIGHUP, reload_action);
631*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
632*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
633*00b67f09SDavid van Moolenbroek }
634*00b67f09SDavid van Moolenbroek
635*00b67f09SDavid van Moolenbroek (void) isc__taskmgr_dispatch(ctx->taskmgr);
636*00b67f09SDavid van Moolenbroek result = evloop(ctx);
637*00b67f09SDavid van Moolenbroek return (result);
638*00b67f09SDavid van Moolenbroek #else /* ISC_PLATFORM_USETHREADS */
639*00b67f09SDavid van Moolenbroek /*
640*00b67f09SDavid van Moolenbroek * BIND9 internal tools using multiple contexts do not
641*00b67f09SDavid van Moolenbroek * rely on signal.
642*00b67f09SDavid van Moolenbroek */
643*00b67f09SDavid van Moolenbroek if (isc_bind9 && ctx != &isc_g_appctx)
644*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
645*00b67f09SDavid van Moolenbroek
646*00b67f09SDavid van Moolenbroek /*
647*00b67f09SDavid van Moolenbroek * There is no danger if isc_app_shutdown() is called before we
648*00b67f09SDavid van Moolenbroek * wait for signals. Signals are blocked, so any such signal will
649*00b67f09SDavid van Moolenbroek * simply be made pending and we will get it when we call
650*00b67f09SDavid van Moolenbroek * sigwait().
651*00b67f09SDavid van Moolenbroek */
652*00b67f09SDavid van Moolenbroek while (!ctx->want_shutdown) {
653*00b67f09SDavid van Moolenbroek #ifdef HAVE_SIGWAIT
654*00b67f09SDavid van Moolenbroek if (isc_bind9) {
655*00b67f09SDavid van Moolenbroek /*
656*00b67f09SDavid van Moolenbroek * BIND9 internal; single context:
657*00b67f09SDavid van Moolenbroek * Wait for SIGHUP, SIGINT, or SIGTERM.
658*00b67f09SDavid van Moolenbroek */
659*00b67f09SDavid van Moolenbroek if (sigemptyset(&sset) != 0 ||
660*00b67f09SDavid van Moolenbroek sigaddset(&sset, SIGHUP) != 0 ||
661*00b67f09SDavid van Moolenbroek sigaddset(&sset, SIGINT) != 0 ||
662*00b67f09SDavid van Moolenbroek sigaddset(&sset, SIGTERM) != 0) {
663*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
664*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
665*00b67f09SDavid van Moolenbroek "isc_app_run() sigsetops: %s",
666*00b67f09SDavid van Moolenbroek strbuf);
667*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTED);
668*00b67f09SDavid van Moolenbroek }
669*00b67f09SDavid van Moolenbroek
670*00b67f09SDavid van Moolenbroek #ifndef HAVE_UNIXWARE_SIGWAIT
671*00b67f09SDavid van Moolenbroek result = sigwait(&sset, &sig);
672*00b67f09SDavid van Moolenbroek if (result == 0) {
673*00b67f09SDavid van Moolenbroek if (sig == SIGINT || sig == SIGTERM)
674*00b67f09SDavid van Moolenbroek ctx->want_shutdown = ISC_TRUE;
675*00b67f09SDavid van Moolenbroek else if (sig == SIGHUP)
676*00b67f09SDavid van Moolenbroek ctx->want_reload = ISC_TRUE;
677*00b67f09SDavid van Moolenbroek }
678*00b67f09SDavid van Moolenbroek
679*00b67f09SDavid van Moolenbroek #else /* Using UnixWare sigwait semantics. */
680*00b67f09SDavid van Moolenbroek sig = sigwait(&sset);
681*00b67f09SDavid van Moolenbroek if (sig >= 0) {
682*00b67f09SDavid van Moolenbroek if (sig == SIGINT || sig == SIGTERM)
683*00b67f09SDavid van Moolenbroek ctx->want_shutdown = ISC_TRUE;
684*00b67f09SDavid van Moolenbroek else if (sig == SIGHUP)
685*00b67f09SDavid van Moolenbroek ctx->want_reload = ISC_TRUE;
686*00b67f09SDavid van Moolenbroek }
687*00b67f09SDavid van Moolenbroek #endif /* HAVE_UNIXWARE_SIGWAIT */
688*00b67f09SDavid van Moolenbroek } else {
689*00b67f09SDavid van Moolenbroek /*
690*00b67f09SDavid van Moolenbroek * External, or BIND9 using multiple contexts:
691*00b67f09SDavid van Moolenbroek * wait until woken up.
692*00b67f09SDavid van Moolenbroek */
693*00b67f09SDavid van Moolenbroek LOCK(&ctx->readylock);
694*00b67f09SDavid van Moolenbroek if (ctx->want_shutdown) {
695*00b67f09SDavid van Moolenbroek /* shutdown() won the race. */
696*00b67f09SDavid van Moolenbroek UNLOCK(&ctx->readylock);
697*00b67f09SDavid van Moolenbroek break;
698*00b67f09SDavid van Moolenbroek }
699*00b67f09SDavid van Moolenbroek if (!ctx->want_reload)
700*00b67f09SDavid van Moolenbroek WAIT(&ctx->ready, &ctx->readylock);
701*00b67f09SDavid van Moolenbroek UNLOCK(&ctx->readylock);
702*00b67f09SDavid van Moolenbroek }
703*00b67f09SDavid van Moolenbroek #else /* Don't have sigwait(). */
704*00b67f09SDavid van Moolenbroek if (isc_bind9) {
705*00b67f09SDavid van Moolenbroek /*
706*00b67f09SDavid van Moolenbroek * BIND9 internal; single context:
707*00b67f09SDavid van Moolenbroek * Install a signal handler for SIGHUP, then wait for
708*00b67f09SDavid van Moolenbroek * all signals.
709*00b67f09SDavid van Moolenbroek */
710*00b67f09SDavid van Moolenbroek result = handle_signal(SIGHUP, reload_action);
711*00b67f09SDavid van Moolenbroek if (result != ISC_R_SUCCESS)
712*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
713*00b67f09SDavid van Moolenbroek
714*00b67f09SDavid van Moolenbroek if (sigemptyset(&sset) != 0) {
715*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
716*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
717*00b67f09SDavid van Moolenbroek "isc_app_run() sigsetops: %s",
718*00b67f09SDavid van Moolenbroek strbuf);
719*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTED);
720*00b67f09SDavid van Moolenbroek }
721*00b67f09SDavid van Moolenbroek #ifdef HAVE_GPERFTOOLS_PROFILER
722*00b67f09SDavid van Moolenbroek if (sigaddset(&sset, SIGALRM) != 0) {
723*00b67f09SDavid van Moolenbroek isc__strerror(errno, strbuf, sizeof(strbuf));
724*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
725*00b67f09SDavid van Moolenbroek "isc_app_run() sigsetops: %s",
726*00b67f09SDavid van Moolenbroek strbuf);
727*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTED);
728*00b67f09SDavid van Moolenbroek }
729*00b67f09SDavid van Moolenbroek #endif
730*00b67f09SDavid van Moolenbroek result = sigsuspend(&sset);
731*00b67f09SDavid van Moolenbroek } else {
732*00b67f09SDavid van Moolenbroek /*
733*00b67f09SDavid van Moolenbroek * External, or BIND9 using multiple contexts:
734*00b67f09SDavid van Moolenbroek * wait until woken up.
735*00b67f09SDavid van Moolenbroek */
736*00b67f09SDavid van Moolenbroek LOCK(&ctx->readylock);
737*00b67f09SDavid van Moolenbroek if (ctx->want_shutdown) {
738*00b67f09SDavid van Moolenbroek /* shutdown() won the race. */
739*00b67f09SDavid van Moolenbroek UNLOCK(&ctx->readylock);
740*00b67f09SDavid van Moolenbroek break;
741*00b67f09SDavid van Moolenbroek }
742*00b67f09SDavid van Moolenbroek if (!ctx->want_reload)
743*00b67f09SDavid van Moolenbroek WAIT(&ctx->ready, &ctx->readylock);
744*00b67f09SDavid van Moolenbroek UNLOCK(&ctx->readylock);
745*00b67f09SDavid van Moolenbroek }
746*00b67f09SDavid van Moolenbroek #endif /* HAVE_SIGWAIT */
747*00b67f09SDavid van Moolenbroek
748*00b67f09SDavid van Moolenbroek if (ctx->want_reload) {
749*00b67f09SDavid van Moolenbroek ctx->want_reload = ISC_FALSE;
750*00b67f09SDavid van Moolenbroek return (ISC_R_RELOAD);
751*00b67f09SDavid van Moolenbroek }
752*00b67f09SDavid van Moolenbroek
753*00b67f09SDavid van Moolenbroek if (ctx->want_shutdown && ctx->blocked)
754*00b67f09SDavid van Moolenbroek exit(1);
755*00b67f09SDavid van Moolenbroek }
756*00b67f09SDavid van Moolenbroek
757*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
758*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
759*00b67f09SDavid van Moolenbroek }
760*00b67f09SDavid van Moolenbroek
761*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_run(void)762*00b67f09SDavid van Moolenbroek isc__app_run(void) {
763*00b67f09SDavid van Moolenbroek return (isc__app_ctxrun((isc_appctx_t *)&isc_g_appctx));
764*00b67f09SDavid van Moolenbroek }
765*00b67f09SDavid van Moolenbroek
766*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_ctxshutdown(isc_appctx_t * ctx0)767*00b67f09SDavid van Moolenbroek isc__app_ctxshutdown(isc_appctx_t *ctx0) {
768*00b67f09SDavid van Moolenbroek isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
769*00b67f09SDavid van Moolenbroek isc_boolean_t want_kill = ISC_TRUE;
770*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
771*00b67f09SDavid van Moolenbroek char strbuf[ISC_STRERRORSIZE];
772*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
773*00b67f09SDavid van Moolenbroek
774*00b67f09SDavid van Moolenbroek REQUIRE(VALID_APPCTX(ctx));
775*00b67f09SDavid van Moolenbroek
776*00b67f09SDavid van Moolenbroek LOCK(&ctx->lock);
777*00b67f09SDavid van Moolenbroek
778*00b67f09SDavid van Moolenbroek REQUIRE(ctx->running);
779*00b67f09SDavid van Moolenbroek
780*00b67f09SDavid van Moolenbroek if (ctx->shutdown_requested)
781*00b67f09SDavid van Moolenbroek want_kill = ISC_FALSE;
782*00b67f09SDavid van Moolenbroek else
783*00b67f09SDavid van Moolenbroek ctx->shutdown_requested = ISC_TRUE;
784*00b67f09SDavid van Moolenbroek
785*00b67f09SDavid van Moolenbroek UNLOCK(&ctx->lock);
786*00b67f09SDavid van Moolenbroek
787*00b67f09SDavid van Moolenbroek if (want_kill) {
788*00b67f09SDavid van Moolenbroek if (isc_bind9 && ctx != &isc_g_appctx)
789*00b67f09SDavid van Moolenbroek /* BIND9 internal, but using multiple contexts */
790*00b67f09SDavid van Moolenbroek ctx->want_shutdown = ISC_TRUE;
791*00b67f09SDavid van Moolenbroek else {
792*00b67f09SDavid van Moolenbroek #ifndef ISC_PLATFORM_USETHREADS
793*00b67f09SDavid van Moolenbroek ctx->want_shutdown = ISC_TRUE;
794*00b67f09SDavid van Moolenbroek #else /* ISC_PLATFORM_USETHREADS */
795*00b67f09SDavid van Moolenbroek #ifdef HAVE_LINUXTHREADS
796*00b67f09SDavid van Moolenbroek if (isc_bind9) {
797*00b67f09SDavid van Moolenbroek /* BIND9 internal, single context */
798*00b67f09SDavid van Moolenbroek int result;
799*00b67f09SDavid van Moolenbroek
800*00b67f09SDavid van Moolenbroek result = pthread_kill(main_thread, SIGTERM);
801*00b67f09SDavid van Moolenbroek if (result != 0) {
802*00b67f09SDavid van Moolenbroek isc__strerror(result,
803*00b67f09SDavid van Moolenbroek strbuf, sizeof(strbuf));
804*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
805*00b67f09SDavid van Moolenbroek "isc_app_shutdown() "
806*00b67f09SDavid van Moolenbroek "pthread_kill: %s",
807*00b67f09SDavid van Moolenbroek strbuf);
808*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTED);
809*00b67f09SDavid van Moolenbroek }
810*00b67f09SDavid van Moolenbroek }
811*00b67f09SDavid van Moolenbroek #else
812*00b67f09SDavid van Moolenbroek if (isc_bind9) {
813*00b67f09SDavid van Moolenbroek /* BIND9 internal, single context */
814*00b67f09SDavid van Moolenbroek if (kill(getpid(), SIGTERM) < 0) {
815*00b67f09SDavid van Moolenbroek isc__strerror(errno,
816*00b67f09SDavid van Moolenbroek strbuf, sizeof(strbuf));
817*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
818*00b67f09SDavid van Moolenbroek "isc_app_shutdown() "
819*00b67f09SDavid van Moolenbroek "kill: %s", strbuf);
820*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTED);
821*00b67f09SDavid van Moolenbroek }
822*00b67f09SDavid van Moolenbroek }
823*00b67f09SDavid van Moolenbroek #endif /* HAVE_LINUXTHREADS */
824*00b67f09SDavid van Moolenbroek else {
825*00b67f09SDavid van Moolenbroek /* External, multiple contexts */
826*00b67f09SDavid van Moolenbroek LOCK(&ctx->readylock);
827*00b67f09SDavid van Moolenbroek ctx->want_shutdown = ISC_TRUE;
828*00b67f09SDavid van Moolenbroek UNLOCK(&ctx->readylock);
829*00b67f09SDavid van Moolenbroek SIGNAL(&ctx->ready);
830*00b67f09SDavid van Moolenbroek }
831*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
832*00b67f09SDavid van Moolenbroek }
833*00b67f09SDavid van Moolenbroek }
834*00b67f09SDavid van Moolenbroek
835*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
836*00b67f09SDavid van Moolenbroek }
837*00b67f09SDavid van Moolenbroek
838*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_shutdown(void)839*00b67f09SDavid van Moolenbroek isc__app_shutdown(void) {
840*00b67f09SDavid van Moolenbroek return (isc__app_ctxshutdown((isc_appctx_t *)&isc_g_appctx));
841*00b67f09SDavid van Moolenbroek }
842*00b67f09SDavid van Moolenbroek
843*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_ctxsuspend(isc_appctx_t * ctx0)844*00b67f09SDavid van Moolenbroek isc__app_ctxsuspend(isc_appctx_t *ctx0) {
845*00b67f09SDavid van Moolenbroek isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
846*00b67f09SDavid van Moolenbroek isc_boolean_t want_kill = ISC_TRUE;
847*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
848*00b67f09SDavid van Moolenbroek char strbuf[ISC_STRERRORSIZE];
849*00b67f09SDavid van Moolenbroek #endif
850*00b67f09SDavid van Moolenbroek
851*00b67f09SDavid van Moolenbroek REQUIRE(VALID_APPCTX(ctx));
852*00b67f09SDavid van Moolenbroek
853*00b67f09SDavid van Moolenbroek LOCK(&ctx->lock);
854*00b67f09SDavid van Moolenbroek
855*00b67f09SDavid van Moolenbroek REQUIRE(ctx->running);
856*00b67f09SDavid van Moolenbroek
857*00b67f09SDavid van Moolenbroek /*
858*00b67f09SDavid van Moolenbroek * Don't send the reload signal if we're shutting down.
859*00b67f09SDavid van Moolenbroek */
860*00b67f09SDavid van Moolenbroek if (ctx->shutdown_requested)
861*00b67f09SDavid van Moolenbroek want_kill = ISC_FALSE;
862*00b67f09SDavid van Moolenbroek
863*00b67f09SDavid van Moolenbroek UNLOCK(&ctx->lock);
864*00b67f09SDavid van Moolenbroek
865*00b67f09SDavid van Moolenbroek if (want_kill) {
866*00b67f09SDavid van Moolenbroek if (isc_bind9 && ctx != &isc_g_appctx)
867*00b67f09SDavid van Moolenbroek /* BIND9 internal, but using multiple contexts */
868*00b67f09SDavid van Moolenbroek ctx->want_reload = ISC_TRUE;
869*00b67f09SDavid van Moolenbroek else {
870*00b67f09SDavid van Moolenbroek #ifndef ISC_PLATFORM_USETHREADS
871*00b67f09SDavid van Moolenbroek ctx->want_reload = ISC_TRUE;
872*00b67f09SDavid van Moolenbroek #else /* ISC_PLATFORM_USETHREADS */
873*00b67f09SDavid van Moolenbroek #ifdef HAVE_LINUXTHREADS
874*00b67f09SDavid van Moolenbroek if (isc_bind9) {
875*00b67f09SDavid van Moolenbroek /* BIND9 internal, single context */
876*00b67f09SDavid van Moolenbroek int result;
877*00b67f09SDavid van Moolenbroek
878*00b67f09SDavid van Moolenbroek result = pthread_kill(main_thread, SIGHUP);
879*00b67f09SDavid van Moolenbroek if (result != 0) {
880*00b67f09SDavid van Moolenbroek isc__strerror(result,
881*00b67f09SDavid van Moolenbroek strbuf, sizeof(strbuf));
882*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
883*00b67f09SDavid van Moolenbroek "isc_app_reload() "
884*00b67f09SDavid van Moolenbroek "pthread_kill: %s",
885*00b67f09SDavid van Moolenbroek strbuf);
886*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTED);
887*00b67f09SDavid van Moolenbroek }
888*00b67f09SDavid van Moolenbroek }
889*00b67f09SDavid van Moolenbroek #else
890*00b67f09SDavid van Moolenbroek if (isc_bind9) {
891*00b67f09SDavid van Moolenbroek /* BIND9 internal, single context */
892*00b67f09SDavid van Moolenbroek if (kill(getpid(), SIGHUP) < 0) {
893*00b67f09SDavid van Moolenbroek isc__strerror(errno,
894*00b67f09SDavid van Moolenbroek strbuf, sizeof(strbuf));
895*00b67f09SDavid van Moolenbroek UNEXPECTED_ERROR(__FILE__, __LINE__,
896*00b67f09SDavid van Moolenbroek "isc_app_reload() "
897*00b67f09SDavid van Moolenbroek "kill: %s", strbuf);
898*00b67f09SDavid van Moolenbroek return (ISC_R_UNEXPECTED);
899*00b67f09SDavid van Moolenbroek }
900*00b67f09SDavid van Moolenbroek }
901*00b67f09SDavid van Moolenbroek #endif /* HAVE_LINUXTHREADS */
902*00b67f09SDavid van Moolenbroek else {
903*00b67f09SDavid van Moolenbroek /* External, multiple contexts */
904*00b67f09SDavid van Moolenbroek LOCK(&ctx->readylock);
905*00b67f09SDavid van Moolenbroek ctx->want_reload = ISC_TRUE;
906*00b67f09SDavid van Moolenbroek UNLOCK(&ctx->readylock);
907*00b67f09SDavid van Moolenbroek SIGNAL(&ctx->ready);
908*00b67f09SDavid van Moolenbroek }
909*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
910*00b67f09SDavid van Moolenbroek }
911*00b67f09SDavid van Moolenbroek }
912*00b67f09SDavid van Moolenbroek
913*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
914*00b67f09SDavid van Moolenbroek }
915*00b67f09SDavid van Moolenbroek
916*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_reload(void)917*00b67f09SDavid van Moolenbroek isc__app_reload(void) {
918*00b67f09SDavid van Moolenbroek return (isc__app_ctxsuspend((isc_appctx_t *)&isc_g_appctx));
919*00b67f09SDavid van Moolenbroek }
920*00b67f09SDavid van Moolenbroek
921*00b67f09SDavid van Moolenbroek void
isc__app_ctxfinish(isc_appctx_t * ctx0)922*00b67f09SDavid van Moolenbroek isc__app_ctxfinish(isc_appctx_t *ctx0) {
923*00b67f09SDavid van Moolenbroek isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
924*00b67f09SDavid van Moolenbroek
925*00b67f09SDavid van Moolenbroek REQUIRE(VALID_APPCTX(ctx));
926*00b67f09SDavid van Moolenbroek
927*00b67f09SDavid van Moolenbroek DESTROYLOCK(&ctx->lock);
928*00b67f09SDavid van Moolenbroek }
929*00b67f09SDavid van Moolenbroek
930*00b67f09SDavid van Moolenbroek void
isc__app_finish(void)931*00b67f09SDavid van Moolenbroek isc__app_finish(void) {
932*00b67f09SDavid van Moolenbroek isc__app_ctxfinish((isc_appctx_t *)&isc_g_appctx);
933*00b67f09SDavid van Moolenbroek }
934*00b67f09SDavid van Moolenbroek
935*00b67f09SDavid van Moolenbroek void
isc__app_block(void)936*00b67f09SDavid van Moolenbroek isc__app_block(void) {
937*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
938*00b67f09SDavid van Moolenbroek sigset_t sset;
939*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
940*00b67f09SDavid van Moolenbroek REQUIRE(isc_g_appctx.running);
941*00b67f09SDavid van Moolenbroek REQUIRE(!isc_g_appctx.blocked);
942*00b67f09SDavid van Moolenbroek
943*00b67f09SDavid van Moolenbroek isc_g_appctx.blocked = ISC_TRUE;
944*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
945*00b67f09SDavid van Moolenbroek blockedthread = pthread_self();
946*00b67f09SDavid van Moolenbroek RUNTIME_CHECK(sigemptyset(&sset) == 0 &&
947*00b67f09SDavid van Moolenbroek sigaddset(&sset, SIGINT) == 0 &&
948*00b67f09SDavid van Moolenbroek sigaddset(&sset, SIGTERM) == 0);
949*00b67f09SDavid van Moolenbroek RUNTIME_CHECK(pthread_sigmask(SIG_UNBLOCK, &sset, NULL) == 0);
950*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
951*00b67f09SDavid van Moolenbroek }
952*00b67f09SDavid van Moolenbroek
953*00b67f09SDavid van Moolenbroek void
isc__app_unblock(void)954*00b67f09SDavid van Moolenbroek isc__app_unblock(void) {
955*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
956*00b67f09SDavid van Moolenbroek sigset_t sset;
957*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
958*00b67f09SDavid van Moolenbroek
959*00b67f09SDavid van Moolenbroek REQUIRE(isc_g_appctx.running);
960*00b67f09SDavid van Moolenbroek REQUIRE(isc_g_appctx.blocked);
961*00b67f09SDavid van Moolenbroek
962*00b67f09SDavid van Moolenbroek isc_g_appctx.blocked = ISC_FALSE;
963*00b67f09SDavid van Moolenbroek
964*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
965*00b67f09SDavid van Moolenbroek REQUIRE(blockedthread == pthread_self());
966*00b67f09SDavid van Moolenbroek
967*00b67f09SDavid van Moolenbroek RUNTIME_CHECK(sigemptyset(&sset) == 0 &&
968*00b67f09SDavid van Moolenbroek sigaddset(&sset, SIGINT) == 0 &&
969*00b67f09SDavid van Moolenbroek sigaddset(&sset, SIGTERM) == 0);
970*00b67f09SDavid van Moolenbroek RUNTIME_CHECK(pthread_sigmask(SIG_BLOCK, &sset, NULL) == 0);
971*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
972*00b67f09SDavid van Moolenbroek }
973*00b67f09SDavid van Moolenbroek
974*00b67f09SDavid van Moolenbroek isc_result_t
isc__appctx_create(isc_mem_t * mctx,isc_appctx_t ** ctxp)975*00b67f09SDavid van Moolenbroek isc__appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) {
976*00b67f09SDavid van Moolenbroek isc__appctx_t *ctx;
977*00b67f09SDavid van Moolenbroek
978*00b67f09SDavid van Moolenbroek REQUIRE(mctx != NULL);
979*00b67f09SDavid van Moolenbroek REQUIRE(ctxp != NULL && *ctxp == NULL);
980*00b67f09SDavid van Moolenbroek
981*00b67f09SDavid van Moolenbroek ctx = isc_mem_get(mctx, sizeof(*ctx));
982*00b67f09SDavid van Moolenbroek if (ctx == NULL)
983*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
984*00b67f09SDavid van Moolenbroek
985*00b67f09SDavid van Moolenbroek ctx->common.impmagic = APPCTX_MAGIC;
986*00b67f09SDavid van Moolenbroek ctx->common.magic = ISCAPI_APPCTX_MAGIC;
987*00b67f09SDavid van Moolenbroek ctx->common.methods = &appmethods.methods;
988*00b67f09SDavid van Moolenbroek
989*00b67f09SDavid van Moolenbroek ctx->mctx = NULL;
990*00b67f09SDavid van Moolenbroek isc_mem_attach(mctx, &ctx->mctx);
991*00b67f09SDavid van Moolenbroek
992*00b67f09SDavid van Moolenbroek ctx->taskmgr = NULL;
993*00b67f09SDavid van Moolenbroek ctx->socketmgr = NULL;
994*00b67f09SDavid van Moolenbroek ctx->timermgr = NULL;
995*00b67f09SDavid van Moolenbroek
996*00b67f09SDavid van Moolenbroek *ctxp = (isc_appctx_t *)ctx;
997*00b67f09SDavid van Moolenbroek
998*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
999*00b67f09SDavid van Moolenbroek }
1000*00b67f09SDavid van Moolenbroek
1001*00b67f09SDavid van Moolenbroek void
isc__appctx_destroy(isc_appctx_t ** ctxp)1002*00b67f09SDavid van Moolenbroek isc__appctx_destroy(isc_appctx_t **ctxp) {
1003*00b67f09SDavid van Moolenbroek isc__appctx_t *ctx;
1004*00b67f09SDavid van Moolenbroek
1005*00b67f09SDavid van Moolenbroek REQUIRE(ctxp != NULL);
1006*00b67f09SDavid van Moolenbroek ctx = (isc__appctx_t *)*ctxp;
1007*00b67f09SDavid van Moolenbroek REQUIRE(VALID_APPCTX(ctx));
1008*00b67f09SDavid van Moolenbroek
1009*00b67f09SDavid van Moolenbroek isc_mem_putanddetach(&ctx->mctx, ctx, sizeof(*ctx));
1010*00b67f09SDavid van Moolenbroek
1011*00b67f09SDavid van Moolenbroek *ctxp = NULL;
1012*00b67f09SDavid van Moolenbroek }
1013*00b67f09SDavid van Moolenbroek
1014*00b67f09SDavid van Moolenbroek void
isc__appctx_settaskmgr(isc_appctx_t * ctx0,isc_taskmgr_t * taskmgr)1015*00b67f09SDavid van Moolenbroek isc__appctx_settaskmgr(isc_appctx_t *ctx0, isc_taskmgr_t *taskmgr) {
1016*00b67f09SDavid van Moolenbroek isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
1017*00b67f09SDavid van Moolenbroek
1018*00b67f09SDavid van Moolenbroek REQUIRE(VALID_APPCTX(ctx));
1019*00b67f09SDavid van Moolenbroek
1020*00b67f09SDavid van Moolenbroek ctx->taskmgr = taskmgr;
1021*00b67f09SDavid van Moolenbroek }
1022*00b67f09SDavid van Moolenbroek
1023*00b67f09SDavid van Moolenbroek void
isc__appctx_setsocketmgr(isc_appctx_t * ctx0,isc_socketmgr_t * socketmgr)1024*00b67f09SDavid van Moolenbroek isc__appctx_setsocketmgr(isc_appctx_t *ctx0, isc_socketmgr_t *socketmgr) {
1025*00b67f09SDavid van Moolenbroek isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
1026*00b67f09SDavid van Moolenbroek
1027*00b67f09SDavid van Moolenbroek REQUIRE(VALID_APPCTX(ctx));
1028*00b67f09SDavid van Moolenbroek
1029*00b67f09SDavid van Moolenbroek ctx->socketmgr = socketmgr;
1030*00b67f09SDavid van Moolenbroek }
1031*00b67f09SDavid van Moolenbroek
1032*00b67f09SDavid van Moolenbroek void
isc__appctx_settimermgr(isc_appctx_t * ctx0,isc_timermgr_t * timermgr)1033*00b67f09SDavid van Moolenbroek isc__appctx_settimermgr(isc_appctx_t *ctx0, isc_timermgr_t *timermgr) {
1034*00b67f09SDavid van Moolenbroek isc__appctx_t *ctx = (isc__appctx_t *)ctx0;
1035*00b67f09SDavid van Moolenbroek
1036*00b67f09SDavid van Moolenbroek REQUIRE(VALID_APPCTX(ctx));
1037*00b67f09SDavid van Moolenbroek
1038*00b67f09SDavid van Moolenbroek ctx->timermgr = timermgr;
1039*00b67f09SDavid van Moolenbroek }
1040*00b67f09SDavid van Moolenbroek
1041*00b67f09SDavid van Moolenbroek isc_result_t
isc__app_register(void)1042*00b67f09SDavid van Moolenbroek isc__app_register(void) {
1043*00b67f09SDavid van Moolenbroek return (isc_app_register(isc__appctx_create));
1044*00b67f09SDavid van Moolenbroek }
1045*00b67f09SDavid van Moolenbroek
1046*00b67f09SDavid van Moolenbroek #include "../app_api.c"
1047