lib/tevent: Add trace point callback
[metze/samba/wip.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         std_ev = talloc_zero(ev, struct std_event_context);
352         if (!std_ev) return -1;
353         std_ev->ev = ev;
354         std_ev->epoll_fd = -1;
355
356         epoll_init_ctx(std_ev);
357
358         ev->additional_data = std_ev;
359         return 0;
360 }
361
362 /*
363   recalculate the maxfd
364 */
365 static void calc_maxfd(struct std_event_context *std_ev)
366 {
367         struct tevent_fd *fde;
368
369         std_ev->maxfd = 0;
370         for (fde = std_ev->ev->fd_events; fde; fde = fde->next) {
371                 if (fde->fd > std_ev->maxfd) {
372                         std_ev->maxfd = fde->fd;
373                 }
374         }
375 }
376
377
378 /* to mark the ev->maxfd invalid
379  * this means we need to recalculate it
380  */
381 #define EVENT_INVALID_MAXFD (-1)
382
383 /*
384   destroy an fd_event
385 */
386 static int std_event_fd_destructor(struct tevent_fd *fde)
387 {
388         struct tevent_context *ev = fde->event_ctx;
389         struct std_event_context *std_ev = NULL;
390
391         if (ev) {
392                 std_ev = talloc_get_type(ev->additional_data,
393                                          struct std_event_context);
394
395                 epoll_check_reopen(std_ev);
396
397                 if (std_ev->maxfd == fde->fd) {
398                         std_ev->maxfd = EVENT_INVALID_MAXFD;
399                 }
400
401                 epoll_del_event(std_ev, fde);
402         }
403
404         return tevent_common_fd_destructor(fde);
405 }
406
407 /*
408   add a fd based event
409   return NULL on failure (memory allocation error)
410 */
411 static struct tevent_fd *std_event_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx,
412                                           int fd, uint16_t flags,
413                                           tevent_fd_handler_t handler,
414                                           void *private_data,
415                                           const char *handler_name,
416                                           const char *location)
417 {
418         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
419                                                            struct std_event_context);
420         struct tevent_fd *fde;
421
422         epoll_check_reopen(std_ev);
423
424         fde = tevent_common_add_fd(ev, mem_ctx, fd, flags,
425                                    handler, private_data,
426                                    handler_name, location);
427         if (!fde) return NULL;
428
429         if ((std_ev->maxfd != EVENT_INVALID_MAXFD)
430             && (fde->fd > std_ev->maxfd)) {
431                 std_ev->maxfd = fde->fd;
432         }
433         talloc_set_destructor(fde, std_event_fd_destructor);
434
435         epoll_add_event(std_ev, fde);
436
437         return fde;
438 }
439
440 /*
441   set the fd event flags
442 */
443 static void std_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
444 {
445         struct tevent_context *ev;
446         struct std_event_context *std_ev;
447
448         if (fde->flags == flags) return;
449
450         ev = fde->event_ctx;
451         std_ev = talloc_get_type(ev->additional_data, struct std_event_context);
452
453         fde->flags = flags;
454
455         epoll_check_reopen(std_ev);
456
457         epoll_change_event(std_ev, fde);
458 }
459
460 /*
461   event loop handling using select()
462 */
463 static int std_event_loop_select(struct std_event_context *std_ev, struct timeval *tvalp)
464 {
465         fd_set r_fds, w_fds;
466         struct tevent_fd *fde;
467         int selrtn;
468
469         /* we maybe need to recalculate the maxfd */
470         if (std_ev->maxfd == EVENT_INVALID_MAXFD) {
471                 calc_maxfd(std_ev);
472         }
473
474         FD_ZERO(&r_fds);
475         FD_ZERO(&w_fds);
476
477         /* setup any fd events */
478         for (fde = std_ev->ev->fd_events; fde; fde = fde->next) {
479                 if (fde->fd < 0 || fde->fd >= FD_SETSIZE) {
480                         std_ev->exit_code = EBADF;
481                         return -1;
482                 }
483                 if (fde->flags & TEVENT_FD_READ) {
484                         FD_SET(fde->fd, &r_fds);
485                 }
486                 if (fde->flags & TEVENT_FD_WRITE) {
487                         FD_SET(fde->fd, &w_fds);
488                 }
489         }
490
491         if (std_ev->ev->signal_events &&
492             tevent_common_check_signal(std_ev->ev)) {
493                 return 0;
494         }
495
496         selrtn = select(std_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
497
498         if (selrtn == -1 && errno == EINTR && 
499             std_ev->ev->signal_events) {
500                 tevent_common_check_signal(std_ev->ev);
501                 return 0;
502         }
503
504         if (selrtn == -1 && errno == EBADF) {
505                 /* the socket is dead! this should never
506                    happen as the socket should have first been
507                    made readable and that should have removed
508                    the event, so this must be a bug. This is a
509                    fatal error. */
510                 tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
511                              "ERROR: EBADF on std_event_loop_once\n");
512                 std_ev->exit_code = EBADF;
513                 return -1;
514         }
515
516         if (selrtn == 0 && tvalp) {
517                 /* we don't care about a possible delay here */
518                 tevent_common_loop_timer_delay(std_ev->ev);
519                 return 0;
520         }
521
522         if (selrtn > 0) {
523                 /* at least one file descriptor is ready - check
524                    which ones and call the handler, being careful to allow
525                    the handler to remove itself when called */
526                 for (fde = std_ev->ev->fd_events; fde; fde = fde->next) {
527                         uint16_t flags = 0;
528
529                         if (FD_ISSET(fde->fd, &r_fds)) flags |= TEVENT_FD_READ;
530                         if (FD_ISSET(fde->fd, &w_fds)) flags |= TEVENT_FD_WRITE;
531                         if (flags & fde->flags) {
532                                 fde->handler(std_ev->ev, fde, flags, fde->private_data);
533                                 break;
534                         }
535                 }
536         }
537
538         return 0;
539 }               
540
541 /*
542   do a single event loop using the events defined in ev 
543 */
544 static int std_event_loop_once(struct tevent_context *ev, const char *location)
545 {
546         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
547                                                            struct std_event_context);
548         struct timeval tval;
549
550         if (ev->signal_events &&
551             tevent_common_check_signal(ev)) {
552                 return 0;
553         }
554
555         if (ev->immediate_events &&
556             tevent_common_loop_immediate(ev)) {
557                 return 0;
558         }
559
560         tval = tevent_common_loop_timer_delay(ev);
561         if (tevent_timeval_is_zero(&tval)) {
562                 return 0;
563         }
564
565         epoll_check_reopen(std_ev);
566
567         if (epoll_event_loop(std_ev, &tval) == 0) {
568                 return 0;
569         }
570
571         return std_event_loop_select(std_ev, &tval);
572 }
573
574 static const struct tevent_ops std_event_ops = {
575         .context_init           = std_event_context_init,
576         .add_fd                 = std_event_add_fd,
577         .set_fd_close_fn        = tevent_common_fd_set_close_fn,
578         .get_fd_flags           = tevent_common_fd_get_flags,
579         .set_fd_flags           = std_event_set_fd_flags,
580         .add_timer              = tevent_common_add_timer,
581         .schedule_immediate     = tevent_common_schedule_immediate,
582         .add_signal             = tevent_common_add_signal,
583         .loop_once              = std_event_loop_once,
584         .loop_wait              = tevent_common_loop_wait,
585 };
586
587
588 _PRIVATE_ bool tevent_standard_init(void)
589 {
590         return tevent_register_backend("standard", &std_event_ops);
591 }
592