2 Unix SMB/CIFS implementation.
3 main select loop and event handling
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 PLEASE READ THIS BEFORE MODIFYING!
24 This module is a general abstraction for the main select loop and
25 event handling. Do not ever put any localised hacks in here, instead
26 register one of the possible event types and implement that event
29 There are 4 types of event handling that are handled in this module:
31 1) a file descriptor becoming readable or writeable. This is mostly
32 used for network sockets, but can be used for any type of file
33 descriptor. You may only register one handler for each file
34 descriptor/io combination or you will get unpredictable results
35 (this means that you can have a handler for read events, and a
36 separate handler for write events, but not two handlers that are
37 both handling read events)
39 2) a timed event. You can register an event that happens at a
40 specific time. You can register as many of these as you
41 like. When they are called the handler can choose to set the time
42 for the next event. If next_event is not set then the event is removed.
44 3) an event that happens every time through the select loop. These
45 sorts of events should be very fast, as they will occur a
46 lot. Mostly used for things like destroying a talloc context or
47 checking a signal flag.
49 4) an event triggered by a signal. These can be one shot or
50 repeated. You can have more than one handler registered for a
51 single signal if you want to.
53 To setup a set of events you first need to create a event_context
54 structure using the function event_context_init(); This returns a
55 'struct event_context' that you use in all subsequent calls.
57 After that you can add/remove events that you are interested in
58 using event_add_*() and event_remove_*().
60 Finally, you call event_loop_wait() to block waiting for one of the
61 events to occor. In normal operation event_loop_wait() will loop
62 forever, unless you call event_loop_exit() from inside one of your
70 create a event_context structure. This must be the first events
71 call, and all subsequent calls pass this event_context as the first
72 element. Event handlers also receive this as their first argument.
74 struct event_context *event_context_init(TALLOC_CTX *mem_ctx)
76 struct event_context *ev;
78 ev = talloc_p(mem_ctx, struct event_context);
81 /* start off with no events */
84 ev->events = talloc(ev, 0);
90 destroy an events context, also destroying any remaining events
92 void event_context_destroy(struct event_context *ev)
101 static void calc_maxfd(struct event_context *ev)
105 for (e=ev->fd_events; e; e=e->next) {
114 move the event structures from ev2 into ev, upping the reference
115 count on ev. The event context ev2 is then destroyed.
117 this is used by modules that need to call on the events of a lower module
119 struct event_context *event_context_merge(struct event_context *ev, struct event_context *ev2)
121 DLIST_CONCATENATE(ev->fd_events, ev2->fd_events, struct fd_event *);
122 DLIST_CONCATENATE(ev->timed_events, ev2->timed_events, struct timed_event *);
123 DLIST_CONCATENATE(ev->loop_events, ev2->loop_events, struct loop_event *);
125 ev2->fd_events = NULL;
126 ev2->timed_events = NULL;
127 ev2->loop_events = NULL;
129 talloc_steal(ev->events, ev2->events);
131 event_context_destroy(ev2);
141 return NULL on failure (memory allocation error)
143 struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e)
145 e = talloc_memdup(ev->events, e, sizeof(*e));
147 DLIST_ADD(ev->fd_events, e);
149 if (e->fd > ev->maxfd) {
156 /* to mark the ev->maxfd invalid
157 * this means we need to recalculate it
159 #define EVENT_INVALID_MAXFD (-1)
162 remove a fd based event
163 the event to remove is matched by looking at the handler
164 function and the file descriptor
165 return False on failure (event not found)
167 BOOL event_remove_fd(struct event_context *ev, struct fd_event *e1)
170 for (e=ev->fd_events; e; e=e->next) {
173 e->handler == e1->handler) {
182 remove all fd based events that match a specified fd
184 void event_remove_fd_all(struct event_context *ev, int fd)
187 for (e=ev->fd_events; e; e=e->next) {
188 if (e->ref_count && e->fd == fd) {
195 remove all fd based events that match a specified handler
197 void event_remove_fd_all_handler(struct event_context *ev, void *handler)
200 for (e=ev->fd_events; e; e=e->next) {
202 handler == (void *)e->handler) {
211 return NULL on failure (memory allocation error)
213 struct timed_event *event_add_timed(struct event_context *ev, struct timed_event *e)
215 e = talloc_memdup(ev->events, e, sizeof(*e));
218 DLIST_ADD(ev->timed_events, e);
224 return False on failure (event not found)
226 BOOL event_remove_timed(struct event_context *ev, struct timed_event *e1)
228 struct timed_event *e;
229 for (e=ev->timed_events; e; e=e->next) {
230 if (e->ref_count && e == e1) {
240 return NULL on failure (memory allocation error)
242 struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e)
244 e = talloc_memdup(ev->events, e, sizeof(*e));
247 DLIST_ADD(ev->loop_events, e);
253 the event to remove is matched only on the handler function
254 return False on failure (memory allocation error)
256 BOOL event_remove_loop(struct event_context *ev, struct loop_event *e1)
258 struct loop_event *e;
259 for (e=ev->loop_events; e; e=e->next) {
261 e->handler == e1->handler) {
271 tell the event loop to exit with the specified code
273 void event_loop_exit(struct event_context *ev, int code)
275 ev->exit.exit_now = True;
276 ev->exit.code = code;
280 do a single event loop using the events defined in ev this function
282 int event_loop_once(struct event_context *ev)
287 struct loop_event *le;
288 struct timed_event *te;
294 /* the loop events are called on each loop. Be careful to allow the
295 event to remove itself */
296 for (le=ev->loop_events;le;) {
297 struct loop_event *next = le->next;
298 if (le->ref_count == 0) {
299 DLIST_REMOVE(ev->loop_events, le);
303 le->handler(ev, le, t);
313 /* setup any fd events */
314 for (fe=ev->fd_events; fe; ) {
315 struct fd_event *next = fe->next;
316 if (fe->ref_count == 0) {
317 DLIST_REMOVE(ev->fd_events, fe);
318 if (ev->maxfd == fe->fd) {
319 ev->maxfd = EVENT_INVALID_MAXFD;
323 if (fe->flags & EVENT_FD_READ) {
324 FD_SET(fe->fd, &r_fds);
326 if (fe->flags & EVENT_FD_WRITE) {
327 FD_SET(fe->fd, &w_fds);
333 /* start with a reasonable max timeout */
336 /* work out the right timeout for all timed events */
337 for (te=ev->timed_events;te;te=te->next) {
338 int timeout = te->next_event - t;
343 timeout < tval.tv_sec) {
344 tval.tv_sec = timeout;
348 /* only do a select() if there're fd_events
349 * otherwise we would block for a the time in tval,
350 * and if there're no fd_events present anymore we want to
351 * leave the event loop directly
354 /* we maybe need to recalculate the maxfd */
355 if (ev->maxfd == EVENT_INVALID_MAXFD) {
360 * we don't use sys_select() as it isn't thread
361 * safe. We need to replace the magic pipe handling in
362 * sys_select() with something in the events
363 * structure - for now just use select()
365 selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, &tval);
369 if (selrtn == -1 && errno == EBADF) {
370 /* the socket is dead! this should never
371 happen as the socket should have first been
372 made readable and that should have removed
373 the event, so this must be a bug. This is a
375 DEBUG(0,("EBADF on event_loop_once - exiting\n"));
376 ev->exit.code = EBADF;
381 /* at least one file descriptor is ready - check
382 which ones and call the handler, being careful to allow
383 the handler to remove itself when called */
384 for (fe=ev->fd_events; fe; fe=fe->next) {
386 if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ;
387 if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE;
388 if (fe->ref_count && flags) {
390 fe->handler(ev, fe, t, flags);
397 /* call any timed events that are now due */
398 for (te=ev->timed_events;te;) {
399 struct timed_event *next = te->next;
400 if (te->ref_count == 0) {
401 DLIST_REMOVE(ev->timed_events, te);
403 } else if (te->next_event <= t) {
405 te->handler(ev, te, t);
407 if (te->next_event <= t) {
408 /* the handler didn't set a time for the
409 next event - remove the event */
410 event_remove_timed(ev, te);
420 go into an event loop using the events defined in ev this function
421 will return with the specified code if one of the handlers calls
424 also return (with code 0) if all fd events are removed
426 int event_loop_wait(struct event_context *ev)
428 ZERO_STRUCT(ev->exit);
429 ev->maxfd = EVENT_INVALID_MAXFD;
431 ev->exit.exit_now = False;
433 while (ev->fd_events && !ev->exit.exit_now) {
434 if (event_loop_once(ev) != 0) {
439 return ev->exit.code;