xref: /minix3/external/bsd/bind/dist/bin/tests/shutdown_test.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: shutdown_test.c,v 1.7 2014/12/10 04:37:53 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004, 2007, 2011, 2013  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 1998-2001  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 /* Id: shutdown_test.c,v 1.25 2011/08/28 23:46:41 tbox Exp  */
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek #include <config.h>
23*00b67f09SDavid van Moolenbroek 
24*00b67f09SDavid van Moolenbroek #include <stdlib.h>
25*00b67f09SDavid van Moolenbroek #include <string.h>
26*00b67f09SDavid van Moolenbroek 
27*00b67f09SDavid van Moolenbroek #include <isc/app.h>
28*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
29*00b67f09SDavid van Moolenbroek #include <isc/print.h>
30*00b67f09SDavid van Moolenbroek #include <isc/task.h>
31*00b67f09SDavid van Moolenbroek #include <isc/time.h>
32*00b67f09SDavid van Moolenbroek #include <isc/timer.h>
33*00b67f09SDavid van Moolenbroek #include <isc/util.h>
34*00b67f09SDavid van Moolenbroek 
35*00b67f09SDavid van Moolenbroek typedef struct {
36*00b67f09SDavid van Moolenbroek 	isc_mem_t *	mctx;
37*00b67f09SDavid van Moolenbroek 	isc_task_t *	task;
38*00b67f09SDavid van Moolenbroek 	isc_timer_t *	timer;
39*00b67f09SDavid van Moolenbroek 	unsigned int	ticks;
40*00b67f09SDavid van Moolenbroek 	char	        name[16];
41*00b67f09SDavid van Moolenbroek 	isc_boolean_t	exiting;
42*00b67f09SDavid van Moolenbroek 	isc_task_t *	peer;
43*00b67f09SDavid van Moolenbroek } t_info;
44*00b67f09SDavid van Moolenbroek 
45*00b67f09SDavid van Moolenbroek #define MAX_TASKS	3
46*00b67f09SDavid van Moolenbroek #define T2_SHUTDOWNOK	(ISC_EVENTCLASS(1024) + 0)
47*00b67f09SDavid van Moolenbroek #define T2_SHUTDOWNDONE	(ISC_EVENTCLASS(1024) + 1)
48*00b67f09SDavid van Moolenbroek #define FOO_EVENT	(ISC_EVENTCLASS(1024) + 2)
49*00b67f09SDavid van Moolenbroek 
50*00b67f09SDavid van Moolenbroek static t_info			tasks[MAX_TASKS];
51*00b67f09SDavid van Moolenbroek static unsigned int		task_count;
52*00b67f09SDavid van Moolenbroek static isc_taskmgr_t *		task_manager;
53*00b67f09SDavid van Moolenbroek static isc_timermgr_t *		timer_manager;
54*00b67f09SDavid van Moolenbroek 
55*00b67f09SDavid van Moolenbroek static void
t1_shutdown(isc_task_t * task,isc_event_t * event)56*00b67f09SDavid van Moolenbroek t1_shutdown(isc_task_t *task, isc_event_t *event) {
57*00b67f09SDavid van Moolenbroek 	t_info *info = event->ev_arg;
58*00b67f09SDavid van Moolenbroek 
59*00b67f09SDavid van Moolenbroek 	printf("task %s (%p) t1_shutdown\n", info->name, task);
60*00b67f09SDavid van Moolenbroek 	isc_task_detach(&info->task);
61*00b67f09SDavid van Moolenbroek 	isc_event_free(&event);
62*00b67f09SDavid van Moolenbroek }
63*00b67f09SDavid van Moolenbroek 
64*00b67f09SDavid van Moolenbroek static void
t2_shutdown(isc_task_t * task,isc_event_t * event)65*00b67f09SDavid van Moolenbroek t2_shutdown(isc_task_t *task, isc_event_t *event) {
66*00b67f09SDavid van Moolenbroek 	t_info *info = event->ev_arg;
67*00b67f09SDavid van Moolenbroek 
68*00b67f09SDavid van Moolenbroek 	printf("task %s (%p) t2_shutdown\n", info->name, task);
69*00b67f09SDavid van Moolenbroek 	info->exiting = ISC_TRUE;
70*00b67f09SDavid van Moolenbroek 	isc_event_free(&event);
71*00b67f09SDavid van Moolenbroek }
72*00b67f09SDavid van Moolenbroek 
73*00b67f09SDavid van Moolenbroek static void
shutdown_action(isc_task_t * task,isc_event_t * event)74*00b67f09SDavid van Moolenbroek shutdown_action(isc_task_t *task, isc_event_t *event) {
75*00b67f09SDavid van Moolenbroek 	t_info *info = event->ev_arg;
76*00b67f09SDavid van Moolenbroek 	isc_event_t *nevent;
77*00b67f09SDavid van Moolenbroek 
78*00b67f09SDavid van Moolenbroek 	INSIST(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
79*00b67f09SDavid van Moolenbroek 
80*00b67f09SDavid van Moolenbroek 	printf("task %s (%p) shutdown\n", info->name, task);
81*00b67f09SDavid van Moolenbroek 	if (strcmp(info->name, "0") == 0) {
82*00b67f09SDavid van Moolenbroek 		isc_timer_detach(&info->timer);
83*00b67f09SDavid van Moolenbroek 		nevent = isc_event_allocate(info->mctx, info, T2_SHUTDOWNOK,
84*00b67f09SDavid van Moolenbroek 					    t2_shutdown, &tasks[1],
85*00b67f09SDavid van Moolenbroek 					    sizeof(*event));
86*00b67f09SDavid van Moolenbroek 		RUNTIME_CHECK(nevent != NULL);
87*00b67f09SDavid van Moolenbroek 		info->exiting = ISC_TRUE;
88*00b67f09SDavid van Moolenbroek 		isc_task_sendanddetach(&info->peer, &nevent);
89*00b67f09SDavid van Moolenbroek 	}
90*00b67f09SDavid van Moolenbroek 	isc_event_free(&event);
91*00b67f09SDavid van Moolenbroek }
92*00b67f09SDavid van Moolenbroek 
93*00b67f09SDavid van Moolenbroek static void
foo_event(isc_task_t * task,isc_event_t * event)94*00b67f09SDavid van Moolenbroek foo_event(isc_task_t *task, isc_event_t *event) {
95*00b67f09SDavid van Moolenbroek 	printf("task(%p) foo\n", task);
96*00b67f09SDavid van Moolenbroek 	isc_event_free(&event);
97*00b67f09SDavid van Moolenbroek }
98*00b67f09SDavid van Moolenbroek 
99*00b67f09SDavid van Moolenbroek static void
tick(isc_task_t * task,isc_event_t * event)100*00b67f09SDavid van Moolenbroek tick(isc_task_t *task, isc_event_t *event) {
101*00b67f09SDavid van Moolenbroek 	t_info *info = event->ev_arg;
102*00b67f09SDavid van Moolenbroek 	isc_event_t *nevent;
103*00b67f09SDavid van Moolenbroek 
104*00b67f09SDavid van Moolenbroek 	INSIST(event->ev_type == ISC_TIMEREVENT_TICK);
105*00b67f09SDavid van Moolenbroek 
106*00b67f09SDavid van Moolenbroek 	printf("task %s (%p) tick\n", info->name, task);
107*00b67f09SDavid van Moolenbroek 
108*00b67f09SDavid van Moolenbroek 	info->ticks++;
109*00b67f09SDavid van Moolenbroek 	if (strcmp(info->name, "1") == 0) {
110*00b67f09SDavid van Moolenbroek 		if (info->ticks == 10) {
111*00b67f09SDavid van Moolenbroek 			RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS);
112*00b67f09SDavid van Moolenbroek 		} else if (info->ticks >= 15 && info->exiting) {
113*00b67f09SDavid van Moolenbroek 			isc_timer_detach(&info->timer);
114*00b67f09SDavid van Moolenbroek 			isc_task_detach(&info->task);
115*00b67f09SDavid van Moolenbroek 			nevent = isc_event_allocate(info->mctx, info,
116*00b67f09SDavid van Moolenbroek 						    T2_SHUTDOWNDONE,
117*00b67f09SDavid van Moolenbroek 						    t1_shutdown, &tasks[0],
118*00b67f09SDavid van Moolenbroek 						    sizeof(*event));
119*00b67f09SDavid van Moolenbroek 			RUNTIME_CHECK(nevent != NULL);
120*00b67f09SDavid van Moolenbroek 			isc_task_send(info->peer, &nevent);
121*00b67f09SDavid van Moolenbroek 			isc_task_detach(&info->peer);
122*00b67f09SDavid van Moolenbroek 		}
123*00b67f09SDavid van Moolenbroek 	} else if (strcmp(info->name, "foo") == 0) {
124*00b67f09SDavid van Moolenbroek 		isc_timer_detach(&info->timer);
125*00b67f09SDavid van Moolenbroek 		nevent = isc_event_allocate(info->mctx, info,
126*00b67f09SDavid van Moolenbroek 					    FOO_EVENT,
127*00b67f09SDavid van Moolenbroek 					    foo_event, task,
128*00b67f09SDavid van Moolenbroek 					    sizeof(*event));
129*00b67f09SDavid van Moolenbroek 		RUNTIME_CHECK(nevent != NULL);
130*00b67f09SDavid van Moolenbroek 		isc_task_sendanddetach(&task, &nevent);
131*00b67f09SDavid van Moolenbroek 	}
132*00b67f09SDavid van Moolenbroek 
133*00b67f09SDavid van Moolenbroek 	isc_event_free(&event);
134*00b67f09SDavid van Moolenbroek }
135*00b67f09SDavid van Moolenbroek 
136*00b67f09SDavid van Moolenbroek static t_info *
new_task(isc_mem_t * mctx,const char * name)137*00b67f09SDavid van Moolenbroek new_task(isc_mem_t *mctx, const char *name) {
138*00b67f09SDavid van Moolenbroek 	t_info *ti;
139*00b67f09SDavid van Moolenbroek 	isc_time_t expires;
140*00b67f09SDavid van Moolenbroek 	isc_interval_t interval;
141*00b67f09SDavid van Moolenbroek 
142*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(task_count < MAX_TASKS);
143*00b67f09SDavid van Moolenbroek 	ti = &tasks[task_count];
144*00b67f09SDavid van Moolenbroek 	ti->mctx = mctx;
145*00b67f09SDavid van Moolenbroek 	ti->task = NULL;
146*00b67f09SDavid van Moolenbroek 	ti->timer = NULL;
147*00b67f09SDavid van Moolenbroek 	ti->ticks = 0;
148*00b67f09SDavid van Moolenbroek 	if (name != NULL) {
149*00b67f09SDavid van Moolenbroek 		INSIST(strlen(name) < sizeof(ti->name));
150*00b67f09SDavid van Moolenbroek 		strcpy(ti->name, name);
151*00b67f09SDavid van Moolenbroek 	} else
152*00b67f09SDavid van Moolenbroek 		sprintf(ti->name, "%d", task_count);
153*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(isc_task_create(task_manager, 0, &ti->task) ==
154*00b67f09SDavid van Moolenbroek 		      ISC_R_SUCCESS);
155*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(isc_task_onshutdown(ti->task, shutdown_action, ti) ==
156*00b67f09SDavid van Moolenbroek 		      ISC_R_SUCCESS);
157*00b67f09SDavid van Moolenbroek 
158*00b67f09SDavid van Moolenbroek 	isc_time_settoepoch(&expires);
159*00b67f09SDavid van Moolenbroek 	isc_interval_set(&interval, 1, 0);
160*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(isc_timer_create(timer_manager, isc_timertype_ticker,
161*00b67f09SDavid van Moolenbroek 				       &expires, &interval, ti->task,
162*00b67f09SDavid van Moolenbroek 				       tick, ti, &ti->timer) ==
163*00b67f09SDavid van Moolenbroek 		      ISC_R_SUCCESS);
164*00b67f09SDavid van Moolenbroek 
165*00b67f09SDavid van Moolenbroek 	task_count++;
166*00b67f09SDavid van Moolenbroek 
167*00b67f09SDavid van Moolenbroek 	return (ti);
168*00b67f09SDavid van Moolenbroek }
169*00b67f09SDavid van Moolenbroek 
170*00b67f09SDavid van Moolenbroek int
main(int argc,char * argv[])171*00b67f09SDavid van Moolenbroek main(int argc, char *argv[]) {
172*00b67f09SDavid van Moolenbroek 	unsigned int workers;
173*00b67f09SDavid van Moolenbroek 	t_info *t1, *t2;
174*00b67f09SDavid van Moolenbroek 	isc_task_t *task;
175*00b67f09SDavid van Moolenbroek 	isc_mem_t *mctx, *mctx2;
176*00b67f09SDavid van Moolenbroek 
177*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);
178*00b67f09SDavid van Moolenbroek 
179*00b67f09SDavid van Moolenbroek 	if (argc > 1) {
180*00b67f09SDavid van Moolenbroek 		workers = atoi(argv[1]);
181*00b67f09SDavid van Moolenbroek 		if (workers < 1)
182*00b67f09SDavid van Moolenbroek 			workers = 1;
183*00b67f09SDavid van Moolenbroek 		if (workers > 8192)
184*00b67f09SDavid van Moolenbroek 			workers = 8192;
185*00b67f09SDavid van Moolenbroek 	} else
186*00b67f09SDavid van Moolenbroek 		workers = 2;
187*00b67f09SDavid van Moolenbroek 	printf("%d workers\n", workers);
188*00b67f09SDavid van Moolenbroek 
189*00b67f09SDavid van Moolenbroek 	mctx = NULL;
190*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
191*00b67f09SDavid van Moolenbroek 	mctx2 = NULL;
192*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx2) == ISC_R_SUCCESS);
193*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &task_manager) ==
194*00b67f09SDavid van Moolenbroek 		      ISC_R_SUCCESS);
195*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(isc_timermgr_create(mctx, &timer_manager) ==
196*00b67f09SDavid van Moolenbroek 		      ISC_R_SUCCESS);
197*00b67f09SDavid van Moolenbroek 
198*00b67f09SDavid van Moolenbroek 	t1 = new_task(mctx, NULL);
199*00b67f09SDavid van Moolenbroek 	t2 = new_task(mctx2, NULL);
200*00b67f09SDavid van Moolenbroek 	isc_task_attach(t2->task, &t1->peer);
201*00b67f09SDavid van Moolenbroek 	isc_task_attach(t1->task, &t2->peer);
202*00b67f09SDavid van Moolenbroek 
203*00b67f09SDavid van Moolenbroek 	/*
204*00b67f09SDavid van Moolenbroek 	 * Test run-triggered shutdown.
205*00b67f09SDavid van Moolenbroek 	 */
206*00b67f09SDavid van Moolenbroek 	(void)new_task(mctx2, "foo");
207*00b67f09SDavid van Moolenbroek 
208*00b67f09SDavid van Moolenbroek 	/*
209*00b67f09SDavid van Moolenbroek 	 * Test implicit shutdown.
210*00b67f09SDavid van Moolenbroek 	 */
211*00b67f09SDavid van Moolenbroek 	task = NULL;
212*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(isc_task_create(task_manager, 0, &task) ==
213*00b67f09SDavid van Moolenbroek 		      ISC_R_SUCCESS);
214*00b67f09SDavid van Moolenbroek 	isc_task_detach(&task);
215*00b67f09SDavid van Moolenbroek 
216*00b67f09SDavid van Moolenbroek 	/*
217*00b67f09SDavid van Moolenbroek 	 * Test anti-zombie code.
218*00b67f09SDavid van Moolenbroek 	 */
219*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(isc_task_create(task_manager, 0, &task) ==
220*00b67f09SDavid van Moolenbroek 		      ISC_R_SUCCESS);
221*00b67f09SDavid van Moolenbroek 	isc_task_detach(&task);
222*00b67f09SDavid van Moolenbroek 
223*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(isc_app_run() == ISC_R_SUCCESS);
224*00b67f09SDavid van Moolenbroek 
225*00b67f09SDavid van Moolenbroek 	isc_taskmgr_destroy(&task_manager);
226*00b67f09SDavid van Moolenbroek 	isc_timermgr_destroy(&timer_manager);
227*00b67f09SDavid van Moolenbroek 
228*00b67f09SDavid van Moolenbroek 	printf("Statistics for mctx:\n");
229*00b67f09SDavid van Moolenbroek 	isc_mem_stats(mctx, stdout);
230*00b67f09SDavid van Moolenbroek 	isc_mem_destroy(&mctx);
231*00b67f09SDavid van Moolenbroek 	printf("Statistics for mctx2:\n");
232*00b67f09SDavid van Moolenbroek 	isc_mem_stats(mctx2, stdout);
233*00b67f09SDavid van Moolenbroek 	isc_mem_destroy(&mctx2);
234*00b67f09SDavid van Moolenbroek 
235*00b67f09SDavid van Moolenbroek 	isc_app_finish();
236*00b67f09SDavid van Moolenbroek 
237*00b67f09SDavid van Moolenbroek 	return (0);
238*00b67f09SDavid van Moolenbroek }
239