dac23ec6bc11ea72c5e55b38f152cbe98bcf6f46
[jelmer/samba4-debian.git] / source / lib / events.c
1 /* 
2    Unix SMB/CIFS implementation.
3    main select loop and event handling
4    Copyright (C) Andrew Tridgell 2003
5    
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.
10    
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.
15    
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.
19 */
20
21 /*
22   PLEASE READ THIS BEFORE MODIFYING!
23
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
27   somewhere else.
28
29   There are 4 types of event handling that are handled in this module:
30
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)
38
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.
43
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.
48
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.
52
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.
56
57   After that you can add/remove events that you are interested in
58   using event_add_*() and event_remove_*().
59
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
63   handler functions.
64
65 */
66
67 #include "includes.h"
68
69 /*
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.
73 */
74 struct event_context *event_context_init(TALLOC_CTX *mem_ctx)
75 {
76         struct event_context *ev;
77
78         ev = talloc_p(mem_ctx, struct event_context);
79         if (!ev) return NULL;
80
81         /* start off with no events */
82         ZERO_STRUCTP(ev);
83
84         ev->events = talloc(ev, 0);
85
86         return ev;
87 }
88
89 /*
90   destroy an events context, also destroying any remaining events
91 */
92 void event_context_destroy(struct event_context *ev)
93 {
94         talloc_free(ev);
95 }
96
97
98 /*
99   recalculate the maxfd
100 */
101 static void calc_maxfd(struct event_context *ev)
102 {
103         struct fd_event *e;
104         ev->maxfd = 0;
105         for (e=ev->fd_events; e; e=e->next) {
106                 if (e->ref_count && 
107                     e->fd > ev->maxfd) {
108                         ev->maxfd = e->fd;
109                 }
110         }
111 }
112
113 /*
114   move the event structures from ev2 into ev, upping the reference
115   count on ev. The event context ev2 is then destroyed.
116
117   this is used by modules that need to call on the events of a lower module
118 */
119 struct event_context *event_context_merge(struct event_context *ev, struct event_context *ev2)
120 {
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 *);
124
125         ev2->fd_events = NULL;
126         ev2->timed_events = NULL;
127         ev2->loop_events = NULL;
128
129         talloc_steal(ev->events, ev2->events);
130
131         event_context_destroy(ev2);
132
133         calc_maxfd(ev);
134
135         return ev;
136 }
137
138
139 /*
140   add a fd based event
141   return NULL on failure (memory allocation error)
142 */
143 struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e) 
144 {
145         e = talloc_memdup(ev->events, e, sizeof(*e));
146         if (!e) return NULL;
147         DLIST_ADD(ev->fd_events, e);
148         e->ref_count = 1;
149         if (e->fd > ev->maxfd) {
150                 ev->maxfd = e->fd;
151         }
152         return e;
153 }
154
155
156 /* to mark the ev->maxfd invalid
157  * this means we need to recalculate it
158  */
159 #define EVENT_INVALID_MAXFD (-1)
160
161 /*
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)
166 */
167 BOOL event_remove_fd(struct event_context *ev, struct fd_event *e1)
168 {
169         struct fd_event *e;
170         for (e=ev->fd_events; e; e=e->next) {
171                 if (e->ref_count &&
172                     e->fd == e1->fd && 
173                     e->handler == e1->handler) {
174                         e->ref_count--;
175                         return True;
176                 }
177         }
178         return False;
179 }
180
181 /*
182   remove all fd based events that match a specified fd
183 */
184 void event_remove_fd_all(struct event_context *ev, int fd)
185 {
186         struct fd_event *e;
187         for (e=ev->fd_events; e; e=e->next) {
188                 if (e->ref_count && e->fd == fd) {
189                         e->ref_count--;
190                 }
191         }
192 }
193
194 /*
195   remove all fd based events that match a specified handler
196 */
197 void event_remove_fd_all_handler(struct event_context *ev, void *handler)
198 {
199         struct fd_event *e;
200         for (e=ev->fd_events; e; e=e->next) {
201                 if (e->ref_count &&
202                     handler == (void *)e->handler) {
203                         e->ref_count--;
204                 }
205         }
206 }
207
208
209 /*
210   add a timed event
211   return NULL on failure (memory allocation error)
212 */
213 struct timed_event *event_add_timed(struct event_context *ev, struct timed_event *e) 
214 {
215         e = talloc_memdup(ev->events, e, sizeof(*e));
216         if (!e) return NULL;
217         e->ref_count = 1;
218         DLIST_ADD(ev->timed_events, e);
219         return e;
220 }
221
222 /*
223   remove a timed event
224   return False on failure (event not found)
225 */
226 BOOL event_remove_timed(struct event_context *ev, struct timed_event *e1) 
227 {
228         struct timed_event *e;
229         for (e=ev->timed_events; e; e=e->next) {
230                 if (e->ref_count && e == e1) {
231                         e->ref_count--;
232                         return True;
233                 }
234         }
235         return False;
236 }
237
238 /*
239   add a loop event
240   return NULL on failure (memory allocation error)
241 */
242 struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e)
243 {
244         e = talloc_memdup(ev->events, e, sizeof(*e));
245         if (!e) return NULL;
246         e->ref_count = 1;
247         DLIST_ADD(ev->loop_events, e);
248         return e;
249 }
250
251 /*
252   remove a loop event
253   the event to remove is matched only on the handler function
254   return False on failure (memory allocation error)
255 */
256 BOOL event_remove_loop(struct event_context *ev, struct loop_event *e1) 
257 {
258         struct loop_event *e;
259         for (e=ev->loop_events; e; e=e->next) {
260                 if (e->ref_count &&
261                     e->handler == e1->handler) {
262                         e->ref_count--;
263                         return True;
264                 }
265         }
266         return False;
267 }
268
269
270 /*
271   tell the event loop to exit with the specified code
272 */
273 void event_loop_exit(struct event_context *ev, int code)
274 {
275         ev->exit.exit_now = True;
276         ev->exit.code = code;
277 }
278
279 /*
280   do a single event loop using the events defined in ev this function
281 */
282 int event_loop_once(struct event_context *ev)
283 {
284         time_t t;
285         fd_set r_fds, w_fds;
286         struct fd_event *fe;
287         struct loop_event *le;
288         struct timed_event *te;
289         int selrtn;
290         struct timeval tval;
291
292         t = time(NULL);
293
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);
300                         talloc_free(le);
301                 } else {
302                         le->ref_count++;
303                         le->handler(ev, le, t);
304                         le->ref_count--;
305                 }
306                 le = next;
307         }
308
309         ZERO_STRUCT(tval);
310         FD_ZERO(&r_fds);
311         FD_ZERO(&w_fds);
312
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;
320                         }
321                         talloc_free(fe);
322                 } else {
323                         if (fe->flags & EVENT_FD_READ) {
324                                 FD_SET(fe->fd, &r_fds);
325                         }
326                         if (fe->flags & EVENT_FD_WRITE) {
327                                 FD_SET(fe->fd, &w_fds);
328                         }
329                 }
330                 fe = next;
331         }
332
333         /* start with a reasonable max timeout */
334         tval.tv_sec = 600;
335                 
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;
339                 if (timeout < 0) {
340                         timeout = 0;
341                 }
342                 if (te->ref_count &&
343                     timeout < tval.tv_sec) {
344                         tval.tv_sec = timeout;
345                 }
346         }
347
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
352          */
353         if (ev->fd_events) {
354                 /* we maybe need to recalculate the maxfd */
355                 if (ev->maxfd == EVENT_INVALID_MAXFD) {
356                         calc_maxfd(ev);
357                 }
358                 
359                 /* TODO:
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() 
364                  */
365                 selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, &tval);
366                 
367                 t = time(NULL);
368                 
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
374                            fatal error. */
375                         DEBUG(0,("EBADF on event_loop_once - exiting\n"));
376                         ev->exit.code = EBADF;
377                         return -1;
378                 }
379                 
380                 if (selrtn > 0) {
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) {
385                                 uint16_t flags = 0;
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) {
389                                         fe->ref_count++;
390                                         fe->handler(ev, fe, t, flags);
391                                         fe->ref_count--;
392                                 }
393                         }
394                 }
395         }
396
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);
402                         talloc_free(te);
403                 } else if (te->next_event <= t) {
404                         te->ref_count++;
405                         te->handler(ev, te, t);
406                         te->ref_count--;
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);
411                         }
412                 }
413                 te = next;
414         }               
415         
416         return 0;
417 }
418
419 /*
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
422   event_loop_exit()
423
424   also return (with code 0) if all fd events are removed
425 */
426 int event_loop_wait(struct event_context *ev)
427 {
428         ZERO_STRUCT(ev->exit);
429         ev->maxfd = EVENT_INVALID_MAXFD;
430
431         ev->exit.exit_now = False;
432
433         while (ev->fd_events && !ev->exit.exit_now) {
434                 if (event_loop_once(ev) != 0) {
435                         break;
436                 }
437         }
438
439         return ev->exit.code;
440 }