96f938c78ec888498adb40397e9e3ec1bed2acc2
[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         te->next_event = timeval_zero();
339
340         te->handler(ev, te, t, te->private_data);
341
342         /* note the care taken to prevent referencing a event
343            that could have been freed by the handler */
344         if (std_ev->timed_events) {
345                 if (timeval_is_zero(&std_ev->timed_events->next_event)) {
346                         talloc_free(te);
347                 }
348         }
349 }
350
351 #if WITH_EPOLL
352 /*
353   event loop handling using epoll
354 */
355 static int std_event_loop_epoll(struct event_context *ev, struct timeval *tvalp)
356 {
357         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
358                                                            struct std_event_context);
359         int ret, i;
360         const int maxevents = 8;
361         struct epoll_event events[maxevents];
362         uint32_t destruction_count = std_ev->destruction_count;
363         int timeout = -1;
364
365         if (tvalp) {
366                 /* it's better to trigger timed events a bit later than to early */
367                 timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
368         }
369
370         ret = epoll_wait(std_ev->epoll_fd, events, maxevents, timeout);
371
372         if (ret == -1 && errno != EINTR) {
373                 epoll_fallback_to_select(ev, "epoll_wait() failed");
374                 return -1;
375         }
376
377         if (ret == 0 && tvalp) {
378                 std_event_loop_timer(ev);
379                 return 0;
380         }
381
382         for (i=0;i<ret;i++) {
383                 struct fd_event *fde = talloc_get_type(events[i].data.ptr, 
384                                                        struct fd_event);
385                 uint16_t flags = 0;
386
387                 if (fde == NULL) {
388                         epoll_fallback_to_select(ev, "epoll_wait() gave bad data");
389                         return -1;
390                 }
391                 if (events[i].events & (EPOLLIN|EPOLLHUP|EPOLLERR)) 
392                         flags |= EVENT_FD_READ;
393                 if (events[i].events & EPOLLOUT) flags |= EVENT_FD_WRITE;
394                 if (flags) {
395                         fde->handler(ev, fde, flags, fde->private_data);
396                         if (destruction_count != std_ev->destruction_count) {
397                                 break;
398                         }
399                 }
400         }
401
402         return 0;
403 }               
404 #endif
405
406 /*
407   event loop handling using select()
408 */
409 static int std_event_loop_select(struct event_context *ev, struct timeval *tvalp)
410 {
411         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
412                                                            struct std_event_context);
413         fd_set r_fds, w_fds;
414         struct fd_event *fde;
415         int selrtn;
416         uint32_t destruction_count = std_ev->destruction_count;
417
418         /* we maybe need to recalculate the maxfd */
419         if (std_ev->maxfd == EVENT_INVALID_MAXFD) {
420                 calc_maxfd(ev);
421         }
422
423         FD_ZERO(&r_fds);
424         FD_ZERO(&w_fds);
425
426         /* setup any fd events */
427         for (fde = std_ev->fd_events; fde; fde = fde->next) {
428                 if (fde->flags & EVENT_FD_READ) {
429                         FD_SET(fde->fd, &r_fds);
430                 }
431                 if (fde->flags & EVENT_FD_WRITE) {
432                         FD_SET(fde->fd, &w_fds);
433                 }
434         }
435
436         selrtn = select(std_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
437
438         if (selrtn == -1 && errno == EBADF) {
439                 /* the socket is dead! this should never
440                    happen as the socket should have first been
441                    made readable and that should have removed
442                    the event, so this must be a bug. This is a
443                    fatal error. */
444                 DEBUG(0,("ERROR: EBADF on std_event_loop_once\n"));
445                 std_ev->exit_code = EBADF;
446                 return -1;
447         }
448
449         if (selrtn == 0 && tvalp) {
450                 std_event_loop_timer(ev);
451                 return 0;
452         }
453
454         if (selrtn > 0) {
455                 /* at least one file descriptor is ready - check
456                    which ones and call the handler, being careful to allow
457                    the handler to remove itself when called */
458                 for (fde = std_ev->fd_events; fde; fde = fde->next) {
459                         uint16_t flags = 0;
460
461                         if (FD_ISSET(fde->fd, &r_fds)) flags |= EVENT_FD_READ;
462                         if (FD_ISSET(fde->fd, &w_fds)) flags |= EVENT_FD_WRITE;
463                         if (flags) {
464                                 fde->handler(ev, fde, flags, fde->private_data);
465                                 if (destruction_count != std_ev->destruction_count) {
466                                         break;
467                                 }
468                         }
469                 }
470         }
471
472         return 0;
473 }               
474
475 /*
476   do a single event loop using the events defined in ev 
477 */
478 static int std_event_loop_once(struct event_context *ev)
479 {
480         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
481                                                            struct std_event_context);
482         struct timeval tval, *tvalp;
483
484         tvalp = NULL;
485
486         /* work out the right timeout for all timed events */
487         if (std_ev->timed_events) {
488                 struct timeval t = timeval_current();
489
490                 tval = timeval_diff(&std_ev->timed_events->next_event, &t);
491                 tvalp = &tval;
492                 if (timeval_is_zero(tvalp)) {
493                         std_event_loop_timer(ev);
494                         return 0;
495                 }
496         }
497
498 #if WITH_EPOLL
499         if (std_ev->epoll_fd != -1) {
500                 if (std_event_loop_epoll(ev, tvalp) == 0) {
501                         return 0;
502                 }
503         }
504 #endif
505
506         return std_event_loop_select(ev, tvalp);
507 }
508
509 /*
510   return on failure or (with 0) if all fd events are removed
511 */
512 static int std_event_loop_wait(struct event_context *ev)
513 {
514         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
515                                                            struct std_event_context);
516         std_ev->exit_code = 0;
517         std_ev->maxfd = EVENT_INVALID_MAXFD;
518
519         while (std_ev->fd_events && std_ev->exit_code == 0) {
520                 if (std_event_loop_once(ev) != 0) {
521                         break;
522                 }
523         }
524
525         return std_ev->exit_code;
526 }
527
528 static const struct event_ops std_event_ops = {
529         .context_init   = std_event_context_init,
530         .add_fd         = std_event_add_fd,
531         .get_fd_flags   = std_event_get_fd_flags,
532         .set_fd_flags   = std_event_set_fd_flags,
533         .add_timed      = std_event_add_timed,
534         .loop_once      = std_event_loop_once,
535         .loop_wait      = std_event_loop_wait,
536 };
537
538 const struct event_ops *event_standard_get_ops(void)
539 {
540         return &std_event_ops;
541 }