r8409: fixed another error found on netbsd.
[bbaumbach/samba-autobuild/.git] / source4 / lib / events / events_standard.c
1 /* 
2    Unix SMB/CIFS implementation.
3    main select loop and event handling
4    Copyright (C) Andrew Tridgell        2003-2005
5    Copyright (C) Stefan Metzmacher      2005
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 /*
23   This is SAMBA's default event loop code
24
25   - we try to use epoll if configure detected support for it
26     otherwise we use select()
27   - if epoll is broken on the system or the kernel doesn't support it
28     at runtime we fallback to select()
29 */
30
31 #include "includes.h"
32 #include "system/filesys.h"
33 #include "dlinklist.h"
34 #include "lib/events/events.h"
35 #include "lib/events/events_internal.h"
36
37 /* use epoll if it is available */
38 #if defined(HAVE_EPOLL_CREATE) && defined(HAVE_SYS_EPOLL_H)
39 #define WITH_EPOLL 1
40 #endif
41
42 #if WITH_EPOLL
43 #include <sys/epoll.h>
44 #endif
45
46 struct std_event_context {
47         /* list of filedescriptor events */
48         struct fd_event *fd_events;
49
50         /* list of timed events */
51         struct timed_event *timed_events;
52
53         /* the maximum file descriptor number in fd_events */
54         int maxfd;
55
56         /* information for exiting from the event loop */
57         int exit_code;
58
59         /* this is changed by the destructors for the fd event
60            type. It is used to detect event destruction by event
61            handlers, which means the code that is calling the event
62            handler needs to assume that the linked list is no longer
63            valid
64         */
65         uint32_t destruction_count;
66
67 #if WITH_EPOLL
68         /* when using epoll this is the handle from epoll_create */
69         int epoll_fd;
70 #endif
71 };
72
73 /*
74   destroy an event context
75 */
76 static int std_event_context_destructor(void *ptr)
77 {
78 #if WITH_EPOLL
79         struct event_context *ev = talloc_get_type(ptr, struct event_context);
80         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
81                                                            struct std_event_context);
82         if (std_ev->epoll_fd != -1) {
83                 close(std_ev->epoll_fd);
84                 std_ev->epoll_fd = -1;
85         }
86 #endif
87         return 0;
88 }
89
90 /*
91   create a std_event_context structure.
92 */
93 static int std_event_context_init(struct event_context *ev, void *privata_data)
94 {
95         struct std_event_context *std_ev;
96
97         std_ev = talloc_zero(ev, struct std_event_context);
98         if (!std_ev) return -1;
99
100 #if WITH_EPOLL
101         std_ev->epoll_fd = epoll_create(64);
102 #endif
103
104         ev->additional_data = std_ev;
105
106         talloc_set_destructor(ev, std_event_context_destructor);
107
108         return 0;
109 }
110
111 /*
112   recalculate the maxfd
113 */
114 static void calc_maxfd(struct event_context *ev)
115 {
116         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
117                                                            struct std_event_context);
118         struct fd_event *fde;
119
120         std_ev->maxfd = 0;
121         for (fde = std_ev->fd_events; fde; fde = fde->next) {
122                 if (fde->fd > std_ev->maxfd) {
123                         std_ev->maxfd = fde->fd;
124                 }
125         }
126 }
127
128
129 /* to mark the ev->maxfd invalid
130  * this means we need to recalculate it
131  */
132 #define EVENT_INVALID_MAXFD (-1)
133
134
135 #if WITH_EPOLL
136 /*
137   called when a epoll call fails, and we should fallback
138   to using select
139 */
140 static void epoll_fallback_to_select(struct event_context *ev, const char *reason)
141 {
142         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
143                                                            struct std_event_context);
144         DEBUG(0,("%s (%s) - falling back to select()\n", reason, strerror(errno)));
145         close(std_ev->epoll_fd);
146         std_ev->epoll_fd = -1;
147 }
148 #endif
149
150
151 #if WITH_EPOLL
152 /*
153   map from EVENT_FD_* to EPOLLIN/EPOLLOUT
154 */
155 static uint32_t epoll_map_flags(uint16_t flags)
156 {
157         uint32_t ret = 0;
158         if (flags & EVENT_FD_READ) ret |= EPOLLIN;
159         if (flags & EVENT_FD_WRITE) ret |= EPOLLOUT;
160         return ret;
161 }
162 #endif
163
164 /*
165   destroy an fd_event
166 */
167 static int std_event_fd_destructor(void *ptr)
168 {
169         struct fd_event *fde = talloc_get_type(ptr, struct fd_event);
170         struct event_context *ev = fde->event_ctx;
171         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
172                                                            struct std_event_context);
173
174         if (std_ev->maxfd == fde->fd) {
175                 std_ev->maxfd = EVENT_INVALID_MAXFD;
176         }
177         DLIST_REMOVE(std_ev->fd_events, fde);
178         std_ev->destruction_count++;
179 #if WITH_EPOLL
180         if (std_ev->epoll_fd != -1) {
181                 struct epoll_event event;
182                 ZERO_STRUCT(event);
183                 event.events = epoll_map_flags(fde->flags);
184                 event.data.ptr = fde;
185                 epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event);
186         }
187 #endif
188         return 0;
189 }
190
191 /*
192   add a fd based event
193   return NULL on failure (memory allocation error)
194 */
195 static struct fd_event *std_event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
196                                          int fd, uint16_t flags,
197                                          event_fd_handler_t handler,
198                                          void *private_data)
199 {
200         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
201                                                            struct std_event_context);
202         struct fd_event *fde;
203
204         fde = talloc(mem_ctx?mem_ctx:ev, struct fd_event);
205         if (!fde) return NULL;
206
207         fde->event_ctx          = ev;
208         fde->fd                 = fd;
209         fde->flags              = flags;
210         fde->handler            = handler;
211         fde->private_data       = private_data;
212         fde->additional_data    = NULL;
213
214         DLIST_ADD(std_ev->fd_events, fde);
215
216         if (fde->fd > std_ev->maxfd) {
217                 std_ev->maxfd = fde->fd;
218         }
219
220         talloc_set_destructor(fde, std_event_fd_destructor);
221
222 #if WITH_EPOLL
223         if (std_ev->epoll_fd != -1) {
224                 struct epoll_event event;
225                 ZERO_STRUCT(event);
226                 event.events = epoll_map_flags(flags);
227                 event.data.ptr = fde;
228                 if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event) != 0) {
229                         epoll_fallback_to_select(ev, "EPOLL_CTL_ADD failed");
230                 }
231         }
232 #endif
233
234         return fde;
235 }
236
237
238 /*
239   return the fd event flags
240 */
241 static uint16_t std_event_get_fd_flags(struct fd_event *fde)
242 {
243         return fde?fde->flags:0;
244 }
245
246 /*
247   set the fd event flags
248 */
249 static void std_event_set_fd_flags(struct fd_event *fde, uint16_t flags)
250 {
251 #if WITH_EPOLL
252         struct event_context *ev;
253         struct std_event_context *std_ev;
254         if (fde == NULL || 
255             fde->flags == flags) {
256                 return;
257         }
258         ev = fde->event_ctx;
259         std_ev = talloc_get_type(ev->additional_data, struct std_event_context);
260         if (std_ev->epoll_fd != -1) {
261                 struct epoll_event event;
262                 ZERO_STRUCT(event);
263                 event.events = epoll_map_flags(flags);
264                 event.data.ptr = fde;
265                 if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) {
266                         epoll_fallback_to_select(ev, "EPOLL_CTL_MOD failed");
267                 }
268         }
269 #endif
270         if (fde) {
271                 fde->flags = flags;
272         }
273 }
274
275 /*
276   destroy a timed event
277 */
278 static int std_event_timed_destructor(void *ptr)
279 {
280         struct timed_event *te = talloc_get_type(ptr, struct timed_event);
281         struct std_event_context *std_ev = talloc_get_type(te->event_ctx->additional_data,
282                                                            struct std_event_context);
283         DLIST_REMOVE(std_ev->timed_events, te);
284         return 0;
285 }
286
287 /*
288   add a timed event
289   return NULL on failure (memory allocation error)
290 */
291 static struct timed_event *std_event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx,
292                                                struct timeval next_event, 
293                                                event_timed_handler_t handler, 
294                                                void *private_data) 
295 {
296         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
297                                                            struct std_event_context);
298         struct timed_event *te, *last_te, *cur_te;
299
300         te = talloc(mem_ctx?mem_ctx:ev, struct timed_event);
301         if (te == NULL) return NULL;
302
303         te->event_ctx           = ev;
304         te->next_event          = next_event;
305         te->handler             = handler;
306         te->private_data        = private_data;
307         te->additional_data     = NULL;
308
309         /* keep the list ordered */
310         last_te = NULL;
311         for (cur_te = std_ev->timed_events; cur_te; cur_te = cur_te->next) {
312                 /* if the new event comes before the current one break */
313                 if (!timeval_is_zero(&cur_te->next_event) &&
314                     timeval_compare(&cur_te->next_event, &te->next_event) < 0) {
315                         break;
316                 }
317
318                 last_te = cur_te;
319         }
320
321         DLIST_ADD_AFTER(std_ev->timed_events, te, last_te);
322
323         talloc_set_destructor(te, std_event_timed_destructor);
324
325         return te;
326 }
327
328 /*
329   a timer has gone off - call it
330 */
331 static void std_event_loop_timer(struct event_context *ev)
332 {
333         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
334                                                            struct std_event_context);
335         struct timeval t = timeval_current();
336         struct timed_event *te = std_ev->timed_events;
337
338         if (te == NULL) {
339                 return;
340         }
341
342         te->next_event = timeval_zero();
343
344         te->handler(ev, te, t, te->private_data);
345
346         /* note the care taken to prevent referencing a event
347            that could have been freed by the handler */
348         if (std_ev->timed_events) {
349                 if (timeval_is_zero(&std_ev->timed_events->next_event)) {
350                         talloc_free(te);
351                 }
352         }
353 }
354
355 #if WITH_EPOLL
356 /*
357   event loop handling using epoll
358 */
359 static int std_event_loop_epoll(struct event_context *ev, struct timeval *tvalp)
360 {
361         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
362                                                            struct std_event_context);
363         int ret, i;
364 #define MAXEVENTS 8
365         struct epoll_event events[MAXEVENTS];
366         uint32_t destruction_count = std_ev->destruction_count;
367         int timeout = -1;
368
369         if (tvalp) {
370                 /* it's better to trigger timed events a bit later than to early */
371                 timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
372         }
373
374         ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout);
375
376         if (ret == -1 && errno != EINTR) {
377                 epoll_fallback_to_select(ev, "epoll_wait() failed");
378                 return -1;
379         }
380
381         if (ret == 0 && tvalp) {
382                 std_event_loop_timer(ev);
383                 return 0;
384         }
385
386         for (i=0;i<ret;i++) {
387                 struct fd_event *fde = talloc_get_type(events[i].data.ptr, 
388                                                        struct fd_event);
389                 uint16_t flags = 0;
390
391                 if (fde == NULL) {
392                         epoll_fallback_to_select(ev, "epoll_wait() gave bad data");
393                         return -1;
394                 }
395                 if (events[i].events & (EPOLLIN|EPOLLHUP|EPOLLERR)) 
396                         flags |= EVENT_FD_READ;
397                 if (events[i].events & EPOLLOUT) flags |= EVENT_FD_WRITE;
398                 if (flags) {
399                         fde->handler(ev, fde, flags, fde->private_data);
400                         if (destruction_count != std_ev->destruction_count) {
401                                 break;
402                         }
403                 }
404         }
405
406         return 0;
407 }               
408 #endif
409
410 /*
411   event loop handling using select()
412 */
413 static int std_event_loop_select(struct event_context *ev, struct timeval *tvalp)
414 {
415         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
416                                                            struct std_event_context);
417         fd_set r_fds, w_fds;
418         struct fd_event *fde;
419         int selrtn;
420         uint32_t destruction_count = std_ev->destruction_count;
421
422         /* we maybe need to recalculate the maxfd */
423         if (std_ev->maxfd == EVENT_INVALID_MAXFD) {
424                 calc_maxfd(ev);
425         }
426
427         FD_ZERO(&r_fds);
428         FD_ZERO(&w_fds);
429
430         /* setup any fd events */
431         for (fde = std_ev->fd_events; fde; fde = fde->next) {
432                 if (fde->flags & EVENT_FD_READ) {
433                         FD_SET(fde->fd, &r_fds);
434                 }
435                 if (fde->flags & EVENT_FD_WRITE) {
436                         FD_SET(fde->fd, &w_fds);
437                 }
438         }
439
440         selrtn = select(std_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
441
442         if (selrtn == -1 && errno == EBADF) {
443                 /* the socket is dead! this should never
444                    happen as the socket should have first been
445                    made readable and that should have removed
446                    the event, so this must be a bug. This is a
447                    fatal error. */
448                 DEBUG(0,("ERROR: EBADF on std_event_loop_once\n"));
449                 std_ev->exit_code = EBADF;
450                 return -1;
451         }
452
453         if (selrtn == 0 && tvalp) {
454                 std_event_loop_timer(ev);
455                 return 0;
456         }
457
458         if (selrtn > 0) {
459                 /* at least one file descriptor is ready - check
460                    which ones and call the handler, being careful to allow
461                    the handler to remove itself when called */
462                 for (fde = std_ev->fd_events; fde; fde = fde->next) {
463                         uint16_t flags = 0;
464
465                         if (FD_ISSET(fde->fd, &r_fds)) flags |= EVENT_FD_READ;
466                         if (FD_ISSET(fde->fd, &w_fds)) flags |= EVENT_FD_WRITE;
467                         if (flags) {
468                                 fde->handler(ev, fde, flags, fde->private_data);
469                                 if (destruction_count != std_ev->destruction_count) {
470                                         break;
471                                 }
472                         }
473                 }
474         }
475
476         return 0;
477 }               
478
479 /*
480   do a single event loop using the events defined in ev 
481 */
482 static int std_event_loop_once(struct event_context *ev)
483 {
484         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
485                                                            struct std_event_context);
486         struct timeval tval;
487
488         /* work out the right timeout for all timed events */
489         if (std_ev->timed_events) {
490                 struct timeval t = timeval_current();
491                 tval = timeval_diff(&std_ev->timed_events->next_event, &t);
492                 if (timeval_is_zero(&tval)) {
493                         std_event_loop_timer(ev);
494                         return 0;
495                 }
496         } else {
497                 /* have a default tick time of 30 seconds. This guarantees
498                    that code that uses its own timeout checking will be
499                    able to proceeed eventually */
500                 tval = timeval_set(30, 0);
501         }
502
503 #if WITH_EPOLL
504         if (std_ev->epoll_fd != -1) {
505                 if (std_event_loop_epoll(ev, &tval) == 0) {
506                         return 0;
507                 }
508         }
509 #endif
510
511         return std_event_loop_select(ev, &tval);
512 }
513
514 /*
515   return on failure or (with 0) if all fd events are removed
516 */
517 static int std_event_loop_wait(struct event_context *ev)
518 {
519         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
520                                                            struct std_event_context);
521         std_ev->exit_code = 0;
522
523         while (std_ev->fd_events && std_ev->exit_code == 0) {
524                 if (std_event_loop_once(ev) != 0) {
525                         break;
526                 }
527         }
528
529         return std_ev->exit_code;
530 }
531
532 static const struct event_ops std_event_ops = {
533         .context_init   = std_event_context_init,
534         .add_fd         = std_event_add_fd,
535         .get_fd_flags   = std_event_get_fd_flags,
536         .set_fd_flags   = std_event_set_fd_flags,
537         .add_timed      = std_event_add_timed,
538         .loop_once      = std_event_loop_once,
539         .loop_wait      = std_event_loop_wait,
540 };
541
542 const struct event_ops *event_standard_get_ops(void)
543 {
544         return &std_event_ops;
545 }