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