]> git.ozlabs.org Git - ccan-lca-2011.git/blob - ccan/tevent/tevent_standard.c
lca2011: hacky import of tevent.
[ccan-lca-2011.git] / ccan / tevent / tevent_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-2009
6
7      ** NOTE! The following LGPL license applies to the tevent
8      ** library. This does NOT imply that all of Samba is released
9      ** under the LGPL
10
11    This library is free software; you can redistribute it and/or
12    modify it under the terms of the GNU Lesser General Public
13    License as published by the Free Software Foundation; either
14    version 3 of the License, or (at your option) any later version.
15
16    This library is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19    Lesser General Public License for more details.
20
21    You should have received a copy of the GNU Lesser General Public
22    License along with this library; if not, see <http://www.gnu.org/licenses/>.
23 */
24
25 /*
26   This is SAMBA's default event loop code
27
28   - we try to use epoll if configure detected support for it
29     otherwise we use select()
30   - if epoll is broken on the system or the kernel doesn't support it
31     at runtime we fallback to select()
32 */
33
34 #include <ccan/tevent/tevent.h>
35 #include <ccan/tevent/tevent_internal.h>
36 #include <ccan/tevent/tevent_util.h>
37 #include <errno.h>
38
39 struct std_event_context {
40         /* a pointer back to the generic event_context */
41         struct tevent_context *ev;
42
43         /* the maximum file descriptor number in fd_events */
44         int maxfd;
45
46         /* information for exiting from the event loop */
47         int exit_code;
48
49         /* when using epoll this is the handle from epoll_create */
50         int epoll_fd;
51
52         /* our pid at the time the epoll_fd was created */
53         pid_t pid;
54 };
55
56 /* use epoll if it is available */
57 #if HAVE_EPOLL
58 /*
59   called when a epoll call fails, and we should fallback
60   to using select
61 */
62 static void epoll_fallback_to_select(struct std_event_context *std_ev, const char *reason)
63 {
64         tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
65                      "%s (%s) - falling back to select()\n",
66                      reason, strerror(errno));
67         close(std_ev->epoll_fd);
68         std_ev->epoll_fd = -1;
69         talloc_set_destructor(std_ev, NULL);
70 }
71
72 /*
73   map from TEVENT_FD_* to EPOLLIN/EPOLLOUT
74 */
75 static uint32_t epoll_map_flags(uint16_t flags)
76 {
77         uint32_t ret = 0;
78         if (flags & TEVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP);
79         if (flags & TEVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP);
80         return ret;
81 }
82
83 /*
84  free the epoll fd
85 */
86 static int epoll_ctx_destructor(struct std_event_context *std_ev)
87 {
88         if (std_ev->epoll_fd != -1) {
89                 close(std_ev->epoll_fd);
90         }
91         std_ev->epoll_fd = -1;
92         return 0;
93 }
94
95 /*
96  init the epoll fd
97 */
98 static void epoll_init_ctx(struct std_event_context *std_ev)
99 {
100         std_ev->epoll_fd = epoll_create(64);
101         std_ev->pid = getpid();
102         talloc_set_destructor(std_ev, epoll_ctx_destructor);
103 }
104
105 static void epoll_add_event(struct std_event_context *std_ev, struct tevent_fd *fde);
106
107 /*
108   reopen the epoll handle when our pid changes
109   see http://junkcode.samba.org/ftp/unpacked/junkcode/epoll_fork.c for an 
110   demonstration of why this is needed
111  */
112 static void epoll_check_reopen(struct std_event_context *std_ev)
113 {
114         struct tevent_fd *fde;
115
116         if (std_ev->pid == getpid()) {
117                 return;
118         }
119
120         close(std_ev->epoll_fd);
121         std_ev->epoll_fd = epoll_create(64);
122         if (std_ev->epoll_fd == -1) {
123                 tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
124                              "Failed to recreate epoll handle after fork\n");
125                 return;
126         }
127         std_ev->pid = getpid();
128         for (fde=std_ev->ev->fd_events;fde;fde=fde->next) {
129                 epoll_add_event(std_ev, fde);
130         }
131 }
132
133 #define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT      (1<<0)
134 #define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR   (1<<1)
135 #define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR      (1<<2)
136
137 /*
138  add the epoll event to the given fd_event
139 */
140 static void epoll_add_event(struct std_event_context *std_ev, struct tevent_fd *fde)
141 {
142         struct epoll_event event;
143         if (std_ev->epoll_fd == -1) return;
144
145         fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
146
147         /* if we don't want events yet, don't add an epoll_event */
148         if (fde->flags == 0) return;
149
150         ZERO_STRUCT(event);
151         event.events = epoll_map_flags(fde->flags);
152         event.data.ptr = fde;
153         if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event) != 0) {
154                 epoll_fallback_to_select(std_ev, "EPOLL_CTL_ADD failed");
155         }
156         fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
157
158         /* only if we want to read we want to tell the event handler about errors */
159         if (fde->flags & TEVENT_FD_READ) {
160                 fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
161         }
162 }
163
164 /*
165  delete the epoll event for given fd_event
166 */
167 static void epoll_del_event(struct std_event_context *std_ev, struct tevent_fd *fde)
168 {
169         struct epoll_event event;
170         if (std_ev->epoll_fd == -1) return;
171
172         fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
173
174         /* if there's no epoll_event, we don't need to delete it */
175         if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT)) return;
176
177         ZERO_STRUCT(event);
178         event.events = epoll_map_flags(fde->flags);
179         event.data.ptr = fde;
180         epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event);
181         fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
182 }
183
184 /*
185  change the epoll event to the given fd_event
186 */
187 static void epoll_mod_event(struct std_event_context *std_ev, struct tevent_fd *fde)
188 {
189         struct epoll_event event;
190         if (std_ev->epoll_fd == -1) return;
191
192         fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
193
194         ZERO_STRUCT(event);
195         event.events = epoll_map_flags(fde->flags);
196         event.data.ptr = fde;
197         if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) {
198                 epoll_fallback_to_select(std_ev, "EPOLL_CTL_MOD failed");
199         }
200
201         /* only if we want to read we want to tell the event handler about errors */
202         if (fde->flags & TEVENT_FD_READ) {
203                 fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
204         }
205 }
206
207 static void epoll_change_event(struct std_event_context *std_ev, struct tevent_fd *fde)
208 {
209         bool got_error = (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR);
210         bool want_read = (fde->flags & TEVENT_FD_READ);
211         bool want_write= (fde->flags & TEVENT_FD_WRITE);
212
213         if (std_ev->epoll_fd == -1) return;
214
215         fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
216
217         /* there's already an event */
218         if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT) {
219                 if (want_read || (want_write && !got_error)) {
220                         epoll_mod_event(std_ev, fde);
221                         return;
222                 }
223                 /* 
224                  * if we want to match the select behavior, we need to remove the epoll_event
225                  * when the caller isn't interested in events.
226                  *
227                  * this is because epoll reports EPOLLERR and EPOLLHUP, even without asking for them
228                  */
229                 epoll_del_event(std_ev, fde);
230                 return;
231         }
232
233         /* there's no epoll_event attached to the fde */
234         if (want_read || (want_write && !got_error)) {
235                 epoll_add_event(std_ev, fde);
236                 return;
237         }
238 }
239
240 /*
241   event loop handling using epoll
242 */
243 static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tvalp)
244 {
245         int ret, i;
246 #define MAXEVENTS 1
247         struct epoll_event events[MAXEVENTS];
248         int timeout = -1;
249
250         if (std_ev->epoll_fd == -1) return -1;
251
252         if (tvalp) {
253                 /* it's better to trigger timed events a bit later than to early */
254                 timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
255         }
256
257         if (std_ev->ev->signal_events &&
258             tevent_common_check_signal(std_ev->ev)) {
259                 return 0;
260         }
261
262         ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout);
263
264         if (ret == -1 && errno == EINTR && std_ev->ev->signal_events) {
265                 if (tevent_common_check_signal(std_ev->ev)) {
266                         return 0;
267                 }
268         }
269
270         if (ret == -1 && errno != EINTR) {
271                 epoll_fallback_to_select(std_ev, "epoll_wait() failed");
272                 return -1;
273         }
274
275         if (ret == 0 && tvalp) {
276                 /* we don't care about a possible delay here */
277                 tevent_common_loop_timer_delay(std_ev->ev);
278                 return 0;
279         }
280
281         for (i=0;i<ret;i++) {
282                 struct tevent_fd *fde = talloc_get_type(events[i].data.ptr, 
283                                                        struct tevent_fd);
284                 uint16_t flags = 0;
285
286                 if (fde == NULL) {
287                         epoll_fallback_to_select(std_ev, "epoll_wait() gave bad data");
288                         return -1;
289                 }
290                 if (events[i].events & (EPOLLHUP|EPOLLERR)) {
291                         fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR;
292                         /*
293                          * if we only wait for TEVENT_FD_WRITE, we should not tell the
294                          * event handler about it, and remove the epoll_event,
295                          * as we only report errors when waiting for read events,
296                          * to match the select() behavior
297                          */
298                         if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) {
299                                 epoll_del_event(std_ev, fde);
300                                 continue;
301                         }
302                         flags |= TEVENT_FD_READ;
303                 }
304                 if (events[i].events & EPOLLIN) flags |= TEVENT_FD_READ;
305                 if (events[i].events & EPOLLOUT) flags |= TEVENT_FD_WRITE;
306                 if (flags) {
307                         fde->handler(std_ev->ev, fde, flags, fde->private_data);
308                         break;
309                 }
310         }
311
312         return 0;
313 }
314 #else
315 #define epoll_init_ctx(std_ev) 
316 #define epoll_add_event(std_ev,fde)
317 #define epoll_del_event(std_ev,fde)
318 #define epoll_change_event(std_ev,fde)
319 #define epoll_event_loop(std_ev,tvalp) (-1)
320 #define epoll_check_reopen(std_ev)
321 #endif
322
323 /*
324   create a std_event_context structure.
325 */
326 static int std_event_context_init(struct tevent_context *ev)
327 {
328         struct std_event_context *std_ev;
329
330         std_ev = talloc_zero(ev, struct std_event_context);
331         if (!std_ev) return -1;
332         std_ev->ev = ev;
333         std_ev->epoll_fd = -1;
334
335         epoll_init_ctx(std_ev);
336
337         ev->additional_data = std_ev;
338         return 0;
339 }
340
341 /*
342   recalculate the maxfd
343 */
344 static void calc_maxfd(struct std_event_context *std_ev)
345 {
346         struct tevent_fd *fde;
347
348         std_ev->maxfd = 0;
349         for (fde = std_ev->ev->fd_events; fde; fde = fde->next) {
350                 if (fde->fd > std_ev->maxfd) {
351                         std_ev->maxfd = fde->fd;
352                 }
353         }
354 }
355
356
357 /* to mark the ev->maxfd invalid
358  * this means we need to recalculate it
359  */
360 #define EVENT_INVALID_MAXFD (-1)
361
362 /*
363   destroy an fd_event
364 */
365 static int std_event_fd_destructor(struct tevent_fd *fde)
366 {
367         struct tevent_context *ev = fde->event_ctx;
368         struct std_event_context *std_ev = NULL;
369
370         if (ev) {
371                 std_ev = talloc_get_type(ev->additional_data,
372                                          struct std_event_context);
373
374                 epoll_check_reopen(std_ev);
375
376                 if (std_ev->maxfd == fde->fd) {
377                         std_ev->maxfd = EVENT_INVALID_MAXFD;
378                 }
379
380                 epoll_del_event(std_ev, fde);
381         }
382
383         return tevent_common_fd_destructor(fde);
384 }
385
386 /*
387   add a fd based event
388   return NULL on failure (memory allocation error)
389 */
390 static struct tevent_fd *std_event_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx,
391                                           int fd, uint16_t flags,
392                                           tevent_fd_handler_t handler,
393                                           void *private_data,
394                                           const char *handler_name,
395                                           const char *location)
396 {
397         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
398                                                            struct std_event_context);
399         struct tevent_fd *fde;
400
401         epoll_check_reopen(std_ev);
402
403         fde = tevent_common_add_fd(ev, mem_ctx, fd, flags,
404                                    handler, private_data,
405                                    handler_name, location);
406         if (!fde) return NULL;
407
408         if ((std_ev->maxfd != EVENT_INVALID_MAXFD)
409             && (fde->fd > std_ev->maxfd)) {
410                 std_ev->maxfd = fde->fd;
411         }
412         talloc_set_destructor(fde, std_event_fd_destructor);
413
414         epoll_add_event(std_ev, fde);
415
416         return fde;
417 }
418
419 /*
420   set the fd event flags
421 */
422 static void std_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
423 {
424         struct tevent_context *ev;
425         struct std_event_context *std_ev;
426
427         if (fde->flags == flags) return;
428
429         ev = fde->event_ctx;
430         std_ev = talloc_get_type(ev->additional_data, struct std_event_context);
431
432         fde->flags = flags;
433
434         epoll_check_reopen(std_ev);
435
436         epoll_change_event(std_ev, fde);
437 }
438
439 /*
440   event loop handling using select()
441 */
442 static int std_event_loop_select(struct std_event_context *std_ev, struct timeval *tvalp)
443 {
444         fd_set r_fds, w_fds;
445         struct tevent_fd *fde;
446         int selrtn;
447
448         /* we maybe need to recalculate the maxfd */
449         if (std_ev->maxfd == EVENT_INVALID_MAXFD) {
450                 calc_maxfd(std_ev);
451         }
452
453         FD_ZERO(&r_fds);
454         FD_ZERO(&w_fds);
455
456         /* setup any fd events */
457         for (fde = std_ev->ev->fd_events; fde; fde = fde->next) {
458                 if (fde->flags & TEVENT_FD_READ) {
459                         FD_SET(fde->fd, &r_fds);
460                 }
461                 if (fde->flags & TEVENT_FD_WRITE) {
462                         FD_SET(fde->fd, &w_fds);
463                 }
464         }
465
466         if (std_ev->ev->signal_events &&
467             tevent_common_check_signal(std_ev->ev)) {
468                 return 0;
469         }
470
471         selrtn = select(std_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
472
473         if (selrtn == -1 && errno == EINTR && 
474             std_ev->ev->signal_events) {
475                 tevent_common_check_signal(std_ev->ev);
476                 return 0;
477         }
478
479         if (selrtn == -1 && errno == EBADF) {
480                 /* the socket is dead! this should never
481                    happen as the socket should have first been
482                    made readable and that should have removed
483                    the event, so this must be a bug. This is a
484                    fatal error. */
485                 tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
486                              "ERROR: EBADF on std_event_loop_once\n");
487                 std_ev->exit_code = EBADF;
488                 return -1;
489         }
490
491         if (selrtn == 0 && tvalp) {
492                 /* we don't care about a possible delay here */
493                 tevent_common_loop_timer_delay(std_ev->ev);
494                 return 0;
495         }
496
497         if (selrtn > 0) {
498                 /* at least one file descriptor is ready - check
499                    which ones and call the handler, being careful to allow
500                    the handler to remove itself when called */
501                 for (fde = std_ev->ev->fd_events; fde; fde = fde->next) {
502                         uint16_t flags = 0;
503
504                         if (FD_ISSET(fde->fd, &r_fds)) flags |= TEVENT_FD_READ;
505                         if (FD_ISSET(fde->fd, &w_fds)) flags |= TEVENT_FD_WRITE;
506                         if (flags & fde->flags) {
507                                 fde->handler(std_ev->ev, fde, flags, fde->private_data);
508                                 break;
509                         }
510                 }
511         }
512
513         return 0;
514 }               
515
516 /*
517   do a single event loop using the events defined in ev 
518 */
519 static int std_event_loop_once(struct tevent_context *ev, const char *location)
520 {
521         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
522                                                            struct std_event_context);
523         struct timeval tval;
524
525         if (ev->signal_events &&
526             tevent_common_check_signal(ev)) {
527                 return 0;
528         }
529
530         if (ev->immediate_events &&
531             tevent_common_loop_immediate(ev)) {
532                 return 0;
533         }
534
535         tval = tevent_common_loop_timer_delay(ev);
536         if (tevent_timeval_is_zero(&tval)) {
537                 return 0;
538         }
539
540         epoll_check_reopen(std_ev);
541
542         if (epoll_event_loop(std_ev, &tval) == 0) {
543                 return 0;
544         }
545
546         return std_event_loop_select(std_ev, &tval);
547 }
548
549 static const struct tevent_ops std_event_ops = {
550         .context_init           = std_event_context_init,
551         .add_fd                 = std_event_add_fd,
552         .set_fd_close_fn        = tevent_common_fd_set_close_fn,
553         .get_fd_flags           = tevent_common_fd_get_flags,
554         .set_fd_flags           = std_event_set_fd_flags,
555         .add_timer              = tevent_common_add_timer,
556         .schedule_immediate     = tevent_common_schedule_immediate,
557         .add_signal             = tevent_common_add_signal,
558         .loop_once              = std_event_loop_once,
559         .loop_wait              = tevent_common_loop_wait,
560 };
561
562
563 _PRIVATE_ bool tevent_standard_init(void)
564 {
565         return tevent_register_backend("standard", &std_event_ops);
566 }
567