1999-05-12 09:48:12 +00:00
|
|
|
/*
|
2013-04-11 23:46:07 +00:00
|
|
|
* Copyright (C) 2004, 2007, 2011, 2013 Internet Systems Consortium, Inc. ("ISC")
|
2001-01-09 22:01:04 +00:00
|
|
|
* Copyright (C) 1998-2001 Internet Software Consortium.
|
2000-08-01 01:33:37 +00:00
|
|
|
*
|
2007-06-18 23:47:57 +00:00
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
1999-05-12 09:48:12 +00:00
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
2000-08-01 01:33:37 +00:00
|
|
|
*
|
2004-03-05 05:14:21 +00:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
|
|
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
|
|
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
|
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
|
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
|
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
1999-05-12 09:48:12 +00:00
|
|
|
*/
|
|
|
|
|
2011-08-28 23:46:41 +00:00
|
|
|
/* $Id: shutdown_test.c,v 1.25 2011/08/28 23:46:41 tbox Exp $ */
|
2000-06-22 22:00:42 +00:00
|
|
|
|
1999-05-12 09:48:12 +00:00
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
2000-11-10 05:34:16 +00:00
|
|
|
#include <string.h>
|
1999-05-12 09:48:12 +00:00
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/app.h>
|
1999-05-12 09:48:12 +00:00
|
|
|
#include <isc/mem.h>
|
2004-08-28 06:20:14 +00:00
|
|
|
#include <isc/print.h>
|
1999-05-12 09:48:12 +00:00
|
|
|
#include <isc/task.h>
|
2000-05-03 21:11:40 +00:00
|
|
|
#include <isc/time.h>
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/timer.h>
|
2000-04-28 02:12:16 +00:00
|
|
|
#include <isc/util.h>
|
1999-05-12 09:48:12 +00:00
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
isc_mem_t * mctx;
|
|
|
|
isc_task_t * task;
|
|
|
|
isc_timer_t * timer;
|
|
|
|
unsigned int ticks;
|
|
|
|
char name[16];
|
|
|
|
isc_boolean_t exiting;
|
|
|
|
isc_task_t * peer;
|
|
|
|
} t_info;
|
|
|
|
|
1999-07-10 01:13:59 +00:00
|
|
|
#define MAX_TASKS 3
|
1999-05-12 09:48:12 +00:00
|
|
|
#define T2_SHUTDOWNOK (ISC_EVENTCLASS(1024) + 0)
|
|
|
|
#define T2_SHUTDOWNDONE (ISC_EVENTCLASS(1024) + 1)
|
1999-07-10 01:13:59 +00:00
|
|
|
#define FOO_EVENT (ISC_EVENTCLASS(1024) + 2)
|
1999-05-12 09:48:12 +00:00
|
|
|
|
|
|
|
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) {
|
2000-04-17 19:22:44 +00:00
|
|
|
t_info *info = event->ev_arg;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-05-12 09:48:12 +00:00
|
|
|
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) {
|
2000-04-17 19:22:44 +00:00
|
|
|
t_info *info = event->ev_arg;
|
1999-05-12 09:48:12 +00:00
|
|
|
|
|
|
|
printf("task %s (%p) t2_shutdown\n", info->name, task);
|
|
|
|
info->exiting = ISC_TRUE;
|
|
|
|
isc_event_free(&event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
shutdown_action(isc_task_t *task, isc_event_t *event) {
|
2000-04-17 19:22:44 +00:00
|
|
|
t_info *info = event->ev_arg;
|
1999-05-12 09:48:12 +00:00
|
|
|
isc_event_t *nevent;
|
|
|
|
|
2000-04-17 19:22:44 +00:00
|
|
|
INSIST(event->ev_type == ISC_TASKEVENT_SHUTDOWN);
|
1999-05-12 09:48:12 +00:00
|
|
|
|
|
|
|
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],
|
2001-11-27 01:56:32 +00:00
|
|
|
sizeof(*event));
|
1999-05-12 09:48:12 +00:00
|
|
|
RUNTIME_CHECK(nevent != NULL);
|
|
|
|
info->exiting = ISC_TRUE;
|
1999-07-10 01:13:59 +00:00
|
|
|
isc_task_sendanddetach(&info->peer, &nevent);
|
1999-05-12 09:48:12 +00:00
|
|
|
}
|
|
|
|
isc_event_free(&event);
|
|
|
|
}
|
|
|
|
|
1999-07-10 01:13:59 +00:00
|
|
|
static void
|
|
|
|
foo_event(isc_task_t *task, isc_event_t *event) {
|
|
|
|
printf("task(%p) foo\n", task);
|
|
|
|
isc_event_free(&event);
|
|
|
|
}
|
|
|
|
|
1999-05-12 09:48:12 +00:00
|
|
|
static void
|
2001-11-27 01:56:32 +00:00
|
|
|
tick(isc_task_t *task, isc_event_t *event) {
|
2000-04-17 19:22:44 +00:00
|
|
|
t_info *info = event->ev_arg;
|
1999-05-12 09:48:12 +00:00
|
|
|
isc_event_t *nevent;
|
|
|
|
|
2000-04-17 19:22:44 +00:00
|
|
|
INSIST(event->ev_type == ISC_TIMEREVENT_TICK);
|
1999-05-12 09:48:12 +00:00
|
|
|
|
|
|
|
printf("task %s (%p) tick\n", info->name, task);
|
|
|
|
|
|
|
|
info->ticks++;
|
|
|
|
if (strcmp(info->name, "1") == 0) {
|
|
|
|
if (info->ticks == 10) {
|
|
|
|
RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS);
|
|
|
|
} 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],
|
2001-11-27 01:56:32 +00:00
|
|
|
sizeof(*event));
|
1999-05-12 09:48:12 +00:00
|
|
|
RUNTIME_CHECK(nevent != NULL);
|
|
|
|
isc_task_send(info->peer, &nevent);
|
|
|
|
isc_task_detach(&info->peer);
|
|
|
|
}
|
1999-07-10 01:13:59 +00:00
|
|
|
} else if (strcmp(info->name, "foo") == 0) {
|
|
|
|
isc_timer_detach(&info->timer);
|
|
|
|
nevent = isc_event_allocate(info->mctx, info,
|
|
|
|
FOO_EVENT,
|
|
|
|
foo_event, task,
|
2001-11-27 01:56:32 +00:00
|
|
|
sizeof(*event));
|
1999-07-10 01:13:59 +00:00
|
|
|
RUNTIME_CHECK(nevent != NULL);
|
|
|
|
isc_task_sendanddetach(&task, &nevent);
|
1999-05-12 09:48:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
isc_event_free(&event);
|
|
|
|
}
|
|
|
|
|
|
|
|
static t_info *
|
2000-06-01 19:11:07 +00:00
|
|
|
new_task(isc_mem_t *mctx, const char *name) {
|
1999-05-12 09:48:12 +00:00
|
|
|
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;
|
1999-07-10 01:13:59 +00:00
|
|
|
if (name != NULL) {
|
2000-06-01 19:11:07 +00:00
|
|
|
INSIST(strlen(name) < sizeof(ti->name));
|
1999-07-10 01:13:59 +00:00
|
|
|
strcpy(ti->name, name);
|
|
|
|
} else
|
|
|
|
sprintf(ti->name, "%d", task_count);
|
2000-04-12 01:41:21 +00:00
|
|
|
RUNTIME_CHECK(isc_task_create(task_manager, 0, &ti->task) ==
|
1999-05-12 09:48:12 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
1999-07-03 21:04:35 +00:00
|
|
|
int
|
1999-05-12 09:48:12 +00:00
|
|
|
main(int argc, char *argv[]) {
|
|
|
|
unsigned int workers;
|
2011-08-28 08:10:13 +00:00
|
|
|
t_info *t1, *t2;
|
1999-07-10 01:13:59 +00:00
|
|
|
isc_task_t *task;
|
1999-05-12 09:48:12 +00:00
|
|
|
isc_mem_t *mctx, *mctx2;
|
|
|
|
|
|
|
|
RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);
|
|
|
|
|
2013-04-11 17:07:50 +10:00
|
|
|
if (argc > 1) {
|
1999-05-12 09:48:12 +00:00
|
|
|
workers = atoi(argv[1]);
|
2013-04-11 17:07:50 +10:00
|
|
|
if (workers < 1)
|
|
|
|
workers = 1;
|
|
|
|
if (workers > 8192)
|
|
|
|
workers = 8192;
|
|
|
|
} else
|
1999-05-12 09:48:12 +00:00
|
|
|
workers = 2;
|
|
|
|
printf("%d workers\n", workers);
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
1999-07-10 01:13:59 +00:00
|
|
|
t1 = new_task(mctx, NULL);
|
|
|
|
t2 = new_task(mctx2, NULL);
|
1999-05-12 09:48:12 +00:00
|
|
|
isc_task_attach(t2->task, &t1->peer);
|
|
|
|
isc_task_attach(t1->task, &t2->peer);
|
|
|
|
|
1999-07-10 01:13:59 +00:00
|
|
|
/*
|
|
|
|
* Test run-triggered shutdown.
|
|
|
|
*/
|
2011-08-28 08:10:13 +00:00
|
|
|
(void)new_task(mctx2, "foo");
|
1999-07-10 01:13:59 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Test implicit shutdown.
|
|
|
|
*/
|
|
|
|
task = NULL;
|
2000-04-12 01:41:21 +00:00
|
|
|
RUNTIME_CHECK(isc_task_create(task_manager, 0, &task) ==
|
1999-07-10 01:13:59 +00:00
|
|
|
ISC_R_SUCCESS);
|
|
|
|
isc_task_detach(&task);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Test anti-zombie code.
|
|
|
|
*/
|
2000-04-12 01:41:21 +00:00
|
|
|
RUNTIME_CHECK(isc_task_create(task_manager, 0, &task) ==
|
1999-07-10 01:13:59 +00:00
|
|
|
ISC_R_SUCCESS);
|
|
|
|
isc_task_detach(&task);
|
|
|
|
|
1999-05-12 09:48:12 +00:00
|
|
|
RUNTIME_CHECK(isc_app_run() == ISC_R_SUCCESS);
|
|
|
|
|
|
|
|
isc_taskmgr_destroy(&task_manager);
|
|
|
|
isc_timermgr_destroy(&timer_manager);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-05-12 09:48:12 +00:00
|
|
|
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();
|
1999-07-03 21:04:35 +00:00
|
|
|
|
|
|
|
return (0);
|
1999-05-12 09:48:12 +00:00
|
|
|
}
|