xref: /minix/external/bsd/bind/dist/lib/isc/unix/app.c (revision 00b67f09)
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