4 * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2001 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: app.c,v 1.9 2009/09/02 23:48:03 tbox Exp */
24 #include <sys/types.h>
33 #include <isc/boolean.h>
34 #include <isc/condition.h>
36 #include <isc/mutex.h>
37 #include <isc/event.h>
38 #include <isc/platform.h>
39 #include <isc/string.h>
43 #include <isc/thread.h>
45 static isc_eventlist_t on_run
;
46 static isc_mutex_t lock
;
47 static isc_boolean_t shutdown_requested
= ISC_FALSE
;
48 static isc_boolean_t running
= ISC_FALSE
;
50 * We assume that 'want_shutdown' can be read and written atomically.
52 static isc_boolean_t want_shutdown
= ISC_FALSE
;
54 * We assume that 'want_reload' can be read and written atomically.
56 static isc_boolean_t want_reload
= ISC_FALSE
;
58 static isc_boolean_t blocked
= ISC_FALSE
;
60 static isc_thread_t blockedthread
;
62 /* Events to wait for */
71 static HANDLE hEvents
[NUM_EVENTS
];
75 * We need to remember which thread is the main thread...
77 static isc_thread_t main_thread
;
80 isc__app_start(void) {
84 * Start an ISC library application.
87 main_thread
= GetCurrentThread();
89 result
= isc_mutex_init(&lock
);
90 if (result
!= ISC_R_SUCCESS
)
93 /* Create the reload event in a non-signaled state */
94 hEvents
[RELOAD_EVENT
] = CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
96 /* Create the shutdown event in a non-signaled state */
97 hEvents
[SHUTDOWN_EVENT
] = CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
99 ISC_LIST_INIT(on_run
);
100 return (ISC_R_SUCCESS
);
104 isc__app_onrun(isc_mem_t
*mctx
, isc_task_t
*task
, isc_taskaction_t action
,
107 isc_task_t
*cloned_task
= NULL
;
113 result
= ISC_R_ALREADYRUNNING
;
118 * Note that we store the task to which we're going to send the event
119 * in the event's "sender" field.
121 isc_task_attach(task
, &cloned_task
);
122 event
= isc_event_allocate(mctx
, cloned_task
, ISC_APPEVENT_SHUTDOWN
,
123 action
, arg
, sizeof(*event
));
125 result
= ISC_R_NOMEMORY
;
129 ISC_LIST_APPEND(on_run
, event
, ev_link
);
130 result
= ISC_R_SUCCESS
;
139 isc_event_t
*event
, *next_event
;
141 HANDLE
*pHandles
= NULL
;
143 REQUIRE(main_thread
== GetCurrentThread());
149 * Post any on-run events (in FIFO order).
151 for (event
= ISC_LIST_HEAD(on_run
);
153 event
= next_event
) {
154 next_event
= ISC_LIST_NEXT(event
, ev_link
);
155 ISC_LIST_UNLINK(on_run
, event
, ev_link
);
156 task
= event
->ev_sender
;
157 event
->ev_sender
= NULL
;
158 isc_task_sendanddetach(&task
, &event
);
166 * There is no danger if isc_app_shutdown() is called before we wait
170 while (!want_shutdown
) {
171 dwWaitResult
= WaitForMultipleObjects(NUM_EVENTS
, hEvents
,
174 /* See why we returned */
176 if (WaitSucceeded(dwWaitResult
, NUM_EVENTS
)) {
178 * The return was due to one of the events
181 switch (WaitSucceededIndex(dwWaitResult
)) {
183 want_reload
= ISC_TRUE
;
187 want_shutdown
= ISC_TRUE
;
192 want_reload
= ISC_FALSE
;
193 return (ISC_R_RELOAD
);
196 if (want_shutdown
&& blocked
)
200 return (ISC_R_SUCCESS
);
204 isc__app_shutdown(void) {
205 isc_boolean_t want_kill
= ISC_TRUE
;
210 if (shutdown_requested
)
211 want_kill
= ISC_FALSE
; /* We're only signaling once */
213 shutdown_requested
= ISC_TRUE
;
217 SetEvent(hEvents
[SHUTDOWN_EVENT
]);
219 return (ISC_R_SUCCESS
);
223 isc__app_reload(void) {
224 isc_boolean_t want_reload
= ISC_TRUE
;
230 * Don't send the reload signal if we're shutting down.
232 if (shutdown_requested
)
233 want_reload
= ISC_FALSE
;
237 SetEvent(hEvents
[RELOAD_EVENT
]);
239 return (ISC_R_SUCCESS
);
243 isc__app_finish(void) {
248 isc__app_block(void) {
253 blockedthread
= GetCurrentThread();
257 isc__app_unblock(void) {
261 REQUIRE(blockedthread
== GetCurrentThread());