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