shutdown_test.c 5.5 KB
Newer Older
Bob Halley's avatar
Bob Halley committed
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4 5 6
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 8 9
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
Bob Halley's avatar
Bob Halley committed
10 11
 */

12
#include <stdbool.h>
Bob Halley's avatar
Bob Halley committed
13
#include <stdlib.h>
Brian Wellington's avatar
Brian Wellington committed
14
#include <string.h>
Bob Halley's avatar
Bob Halley committed
15

16
#include <isc/app.h>
Bob Halley's avatar
Bob Halley committed
17
#include <isc/mem.h>
18
#include <isc/print.h>
19
#include <isc/string.h>
Bob Halley's avatar
Bob Halley committed
20
#include <isc/task.h>
21
#include <isc/time.h>
22
#include <isc/timer.h>
Brian Wellington's avatar
Brian Wellington committed
23
#include <isc/util.h>
Bob Halley's avatar
Bob Halley committed
24 25 26 27 28 29 30

typedef struct {
	isc_mem_t *	mctx;
	isc_task_t *	task;
	isc_timer_t *	timer;
	unsigned int	ticks;
	char	        name[16];
31
	bool	exiting;
Bob Halley's avatar
Bob Halley committed
32 33 34
	isc_task_t *	peer;
} t_info;

35
#define MAX_TASKS	3
Bob Halley's avatar
Bob Halley committed
36 37
#define T2_SHUTDOWNOK	(ISC_EVENTCLASS(1024) + 0)
#define T2_SHUTDOWNDONE	(ISC_EVENTCLASS(1024) + 1)
38
#define FOO_EVENT	(ISC_EVENTCLASS(1024) + 2)
Bob Halley's avatar
Bob Halley committed
39 40 41 42 43 44 45 46

static t_info			tasks[MAX_TASKS];
static unsigned int		task_count;
static isc_taskmgr_t *		task_manager;
static isc_timermgr_t *		timer_manager;

static void
t1_shutdown(isc_task_t *task, isc_event_t *event) {
47
	t_info *info = event->ev_arg;
48

Bob Halley's avatar
Bob Halley committed
49 50 51 52 53 54 55
	printf("task %s (%p) t1_shutdown\n", info->name, task);
	isc_task_detach(&info->task);
	isc_event_free(&event);
}

static void
t2_shutdown(isc_task_t *task, isc_event_t *event) {
56
	t_info *info = event->ev_arg;
Bob Halley's avatar
Bob Halley committed
57 58

	printf("task %s (%p) t2_shutdown\n", info->name, task);
59
	info->exiting = true;
Bob Halley's avatar
Bob Halley committed
60 61 62 63 64
	isc_event_free(&event);
}

static void
shutdown_action(isc_task_t *task, isc_event_t *event) {
65
	t_info *info = event->ev_arg;
Bob Halley's avatar
Bob Halley committed
66 67
	isc_event_t *nevent;

68
	INSIST(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
Bob Halley's avatar
Bob Halley committed
69 70 71 72 73 74

	printf("task %s (%p) shutdown\n", info->name, task);
	if (strcmp(info->name, "0") == 0) {
		isc_timer_detach(&info->timer);
		nevent = isc_event_allocate(info->mctx, info, T2_SHUTDOWNOK,
					    t2_shutdown, &tasks[1],
Andreas Gustafsson's avatar
Andreas Gustafsson committed
75
					    sizeof(*event));
Bob Halley's avatar
Bob Halley committed
76
		RUNTIME_CHECK(nevent != NULL);
77
		info->exiting = true;
78
		isc_task_sendanddetach(&info->peer, &nevent);
Bob Halley's avatar
Bob Halley committed
79 80 81 82
	}
	isc_event_free(&event);
}

83 84 85 86 87 88
static void
foo_event(isc_task_t *task, isc_event_t *event) {
	printf("task(%p) foo\n", task);
	isc_event_free(&event);
}

Bob Halley's avatar
Bob Halley committed
89
static void
Andreas Gustafsson's avatar
Andreas Gustafsson committed
90
tick(isc_task_t *task, isc_event_t *event) {
91
	t_info *info = event->ev_arg;
Bob Halley's avatar
Bob Halley committed
92 93
	isc_event_t *nevent;

94
	INSIST(event->ev_type == ISC_TIMEREVENT_TICK);
Bob Halley's avatar
Bob Halley committed
95 96 97 98 99 100

	printf("task %s (%p) tick\n", info->name, task);

	info->ticks++;
	if (strcmp(info->name, "1") == 0) {
		if (info->ticks == 10) {
101
			isc_app_shutdown();
Bob Halley's avatar
Bob Halley committed
102 103 104 105 106 107
		} else if (info->ticks >= 15 && info->exiting) {
			isc_timer_detach(&info->timer);
			isc_task_detach(&info->task);
			nevent = isc_event_allocate(info->mctx, info,
						    T2_SHUTDOWNDONE,
						    t1_shutdown, &tasks[0],
Andreas Gustafsson's avatar
Andreas Gustafsson committed
108
						    sizeof(*event));
Bob Halley's avatar
Bob Halley committed
109 110 111 112
			RUNTIME_CHECK(nevent != NULL);
			isc_task_send(info->peer, &nevent);
			isc_task_detach(&info->peer);
		}
113 114 115 116 117
	} else if (strcmp(info->name, "foo") == 0) {
		isc_timer_detach(&info->timer);
		nevent = isc_event_allocate(info->mctx, info,
					    FOO_EVENT,
					    foo_event, task,
Andreas Gustafsson's avatar
Andreas Gustafsson committed
118
					    sizeof(*event));
119 120
		RUNTIME_CHECK(nevent != NULL);
		isc_task_sendanddetach(&task, &nevent);
Bob Halley's avatar
Bob Halley committed
121 122 123 124 125 126
	}

	isc_event_free(&event);
}

static t_info *
David Lawrence's avatar
David Lawrence committed
127
new_task(isc_mem_t *mctx, const char *name) {
Bob Halley's avatar
Bob Halley committed
128 129 130 131 132 133 134 135 136 137
	t_info *ti;
	isc_time_t expires;
	isc_interval_t interval;

	RUNTIME_CHECK(task_count < MAX_TASKS);
	ti = &tasks[task_count];
	ti->mctx = mctx;
	ti->task = NULL;
	ti->timer = NULL;
	ti->ticks = 0;
138
	if (name != NULL) {
David Lawrence's avatar
David Lawrence committed
139
		INSIST(strlen(name) < sizeof(ti->name));
Evan Hunt's avatar
Evan Hunt committed
140 141
		strlcpy(ti->name, name, sizeof(ti->name));
	} else {
Mark Andrews's avatar
Mark Andrews committed
142
		snprintf(ti->name, sizeof(ti->name), "%u", task_count);
Evan Hunt's avatar
Evan Hunt committed
143
	}
Bob Halley's avatar
Bob Halley committed
144
	RUNTIME_CHECK(isc_task_create(task_manager, 0, &ti->task) ==
Bob Halley's avatar
Bob Halley committed
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
		      ISC_R_SUCCESS);
	RUNTIME_CHECK(isc_task_onshutdown(ti->task, shutdown_action, ti) ==
		      ISC_R_SUCCESS);

	isc_time_settoepoch(&expires);
	isc_interval_set(&interval, 1, 0);
	RUNTIME_CHECK(isc_timer_create(timer_manager, isc_timertype_ticker,
				       &expires, &interval, ti->task,
				       tick, ti, &ti->timer) ==
		      ISC_R_SUCCESS);

	task_count++;

	return (ti);
}

Bob Halley's avatar
Bob Halley committed
161
int
Bob Halley's avatar
Bob Halley committed
162 163
main(int argc, char *argv[]) {
	unsigned int workers;
Mark Andrews's avatar
Mark Andrews committed
164
	t_info *t1, *t2;
165
	isc_task_t *task;
Bob Halley's avatar
Bob Halley committed
166 167 168 169
	isc_mem_t *mctx, *mctx2;

	RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);

Mark Andrews's avatar
Mark Andrews committed
170
	if (argc > 1) {
Bob Halley's avatar
Bob Halley committed
171
		workers = atoi(argv[1]);
Mark Andrews's avatar
Mark Andrews committed
172 173 174 175 176
		if (workers < 1)
			workers = 1;
		if (workers > 8192)
			workers = 8192;
	} else
Bob Halley's avatar
Bob Halley committed
177
		workers = 2;
Mark Andrews's avatar
Mark Andrews committed
178
	printf("%u workers\n", workers);
Bob Halley's avatar
Bob Halley committed
179 180 181 182 183 184 185 186 187 188

	mctx = NULL;
	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
	mctx2 = NULL;
	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx2) == ISC_R_SUCCESS);
	RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &task_manager) ==
		      ISC_R_SUCCESS);
	RUNTIME_CHECK(isc_timermgr_create(mctx, &timer_manager) ==
		      ISC_R_SUCCESS);

189 190
	t1 = new_task(mctx, NULL);
	t2 = new_task(mctx2, NULL);
Bob Halley's avatar
Bob Halley committed
191 192 193
	isc_task_attach(t2->task, &t1->peer);
	isc_task_attach(t1->task, &t2->peer);

194 195 196
	/*
	 * Test run-triggered shutdown.
	 */
Mark Andrews's avatar
Mark Andrews committed
197
	(void)new_task(mctx2, "foo");
198 199 200 201 202

	/*
	 * Test implicit shutdown.
	 */
	task = NULL;
Bob Halley's avatar
Bob Halley committed
203
	RUNTIME_CHECK(isc_task_create(task_manager, 0, &task) ==
204 205 206 207 208 209
		      ISC_R_SUCCESS);
	isc_task_detach(&task);

	/*
	 * Test anti-zombie code.
	 */
Bob Halley's avatar
Bob Halley committed
210
	RUNTIME_CHECK(isc_task_create(task_manager, 0, &task) ==
211 212 213
		      ISC_R_SUCCESS);
	isc_task_detach(&task);

Bob Halley's avatar
Bob Halley committed
214 215 216 217
	RUNTIME_CHECK(isc_app_run() == ISC_R_SUCCESS);

	isc_taskmgr_destroy(&task_manager);
	isc_timermgr_destroy(&timer_manager);
218

Bob Halley's avatar
Bob Halley committed
219 220 221 222 223 224 225 226
	printf("Statistics for mctx:\n");
	isc_mem_stats(mctx, stdout);
	isc_mem_destroy(&mctx);
	printf("Statistics for mctx2:\n");
	isc_mem_stats(mctx2, stdout);
	isc_mem_destroy(&mctx2);

	isc_app_finish();
Bob Halley's avatar
Bob Halley committed
227 228

	return (0);
Bob Halley's avatar
Bob Halley committed
229
}