tevent: Add a private function tevent_poll_event_add_fd_internal().
[Samba/bjacke.git] / lib / tevent / tevent_standard.c
blob938b2235727fdcc46cd45fe664e6fd03aca5e0d2
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
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
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.
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.
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/>.
26 This is SAMBA's default event loop code
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()
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"
41 struct std_event_context {
42 /* a pointer back to the generic event_context */
43 struct tevent_context *ev;
45 /* the maximum file descriptor number in fd_events */
46 int maxfd;
48 /* information for exiting from the event loop */
49 int exit_code;
51 /* when using epoll this is the handle from epoll_create */
52 int epoll_fd;
54 /* our pid at the time the epoll_fd was created */
55 pid_t pid;
58 /* use epoll if it is available */
59 #if HAVE_EPOLL
61 called when a epoll call fails, and we should fallback
62 to using select
64 static void epoll_fallback_to_select(struct std_event_context *std_ev, const char *reason)
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);
75 map from TEVENT_FD_* to EPOLLIN/EPOLLOUT
77 static uint32_t epoll_map_flags(uint16_t flags)
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;
86 free the epoll fd
88 static int epoll_ctx_destructor(struct std_event_context *std_ev)
90 if (std_ev->epoll_fd != -1) {
91 close(std_ev->epoll_fd);
93 std_ev->epoll_fd = -1;
94 return 0;
98 init the epoll fd
100 static void epoll_init_ctx(struct std_event_context *std_ev)
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;
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");
114 std_ev->pid = getpid();
115 talloc_set_destructor(std_ev, epoll_ctx_destructor);
118 static void epoll_add_event(struct std_event_context *std_ev, struct tevent_fd *fde);
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
125 static void epoll_check_reopen(struct std_event_context *std_ev)
127 struct tevent_fd *fde;
129 if (std_ev->pid == getpid()) {
130 return;
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;
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");
146 std_ev->pid = getpid();
147 for (fde=std_ev->ev->fd_events;fde;fde=fde->next) {
148 epoll_add_event(std_ev, fde);
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)
157 add the epoll event to the given fd_event
159 static void epoll_add_event(struct std_event_context *std_ev, struct tevent_fd *fde)
161 struct epoll_event event;
162 if (std_ev->epoll_fd == -1) return;
164 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
166 /* if we don't want events yet, don't add an epoll_event */
167 if (fde->flags == 0) return;
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");
175 fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
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;
184 delete the epoll event for given fd_event
186 static void epoll_del_event(struct std_event_context *std_ev, struct tevent_fd *fde)
188 struct epoll_event event;
189 if (std_ev->epoll_fd == -1) return;
191 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
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;
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;
204 change the epoll event to the given fd_event
206 static void epoll_mod_event(struct std_event_context *std_ev, struct tevent_fd *fde)
208 struct epoll_event event;
209 if (std_ev->epoll_fd == -1) return;
211 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
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");
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;
226 static void epoll_change_event(struct std_event_context *std_ev, struct tevent_fd *fde)
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);
232 if (std_ev->epoll_fd == -1) return;
234 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
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;
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.
246 * this is because epoll reports EPOLLERR and EPOLLHUP, even without asking for them
248 epoll_del_event(std_ev, fde);
249 return;
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;
260 event loop handling using epoll
262 static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tvalp)
264 int ret, i;
265 #define MAXEVENTS 1
266 struct epoll_event events[MAXEVENTS];
267 int timeout = -1;
269 if (std_ev->epoll_fd == -1) return -1;
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);
276 if (std_ev->ev->signal_events &&
277 tevent_common_check_signal(std_ev->ev)) {
278 return 0;
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);
285 if (ret == -1 && errno == EINTR && std_ev->ev->signal_events) {
286 if (tevent_common_check_signal(std_ev->ev)) {
287 return 0;
291 if (ret == -1 && errno != EINTR) {
292 epoll_fallback_to_select(std_ev, "epoll_wait() failed");
293 return -1;
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;
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;
307 if (fde == NULL) {
308 epoll_fallback_to_select(std_ev, "epoll_wait() gave bad data");
309 return -1;
311 if (events[i].events & (EPOLLHUP|EPOLLERR)) {
312 fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR;
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
319 if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) {
320 epoll_del_event(std_ev, fde);
321 continue;
323 flags |= TEVENT_FD_READ;
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;
333 return 0;
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
345 create a std_event_context structure.
347 static int std_event_context_init(struct tevent_context *ev)
349 struct std_event_context *std_ev;
352 * We might be called during tevent_re_initialise()
353 * which means we need to free our old additional_data.
355 TALLOC_FREE(ev->additional_data);
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;
362 epoll_init_ctx(std_ev);
364 ev->additional_data = std_ev;
365 return 0;
369 recalculate the maxfd
371 static void calc_maxfd(struct std_event_context *std_ev)
373 struct tevent_fd *fde;
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;
384 /* to mark the ev->maxfd invalid
385 * this means we need to recalculate it
387 #define EVENT_INVALID_MAXFD (-1)
390 destroy an fd_event
392 static int std_event_fd_destructor(struct tevent_fd *fde)
394 struct tevent_context *ev = fde->event_ctx;
395 struct std_event_context *std_ev = NULL;
397 if (ev) {
398 std_ev = talloc_get_type(ev->additional_data,
399 struct std_event_context);
401 epoll_check_reopen(std_ev);
403 if (std_ev->maxfd == fde->fd) {
404 std_ev->maxfd = EVENT_INVALID_MAXFD;
407 epoll_del_event(std_ev, fde);
410 return tevent_common_fd_destructor(fde);
414 add a fd based event
415 return NULL on failure (memory allocation error)
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)
424 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
425 struct std_event_context);
426 struct tevent_fd *fde;
428 epoll_check_reopen(std_ev);
430 fde = tevent_common_add_fd(ev, mem_ctx, fd, flags,
431 handler, private_data,
432 handler_name, location);
433 if (!fde) return NULL;
435 if ((std_ev->maxfd != EVENT_INVALID_MAXFD)
436 && (fde->fd > std_ev->maxfd)) {
437 std_ev->maxfd = fde->fd;
439 talloc_set_destructor(fde, std_event_fd_destructor);
441 epoll_add_event(std_ev, fde);
443 return fde;
447 set the fd event flags
449 static void std_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
451 struct tevent_context *ev;
452 struct std_event_context *std_ev;
454 if (fde->flags == flags) return;
456 ev = fde->event_ctx;
457 std_ev = talloc_get_type(ev->additional_data, struct std_event_context);
459 fde->flags = flags;
461 epoll_check_reopen(std_ev);
463 epoll_change_event(std_ev, fde);
467 event loop handling using select()
469 static int std_event_loop_select(struct std_event_context *std_ev, struct timeval *tvalp)
471 fd_set r_fds, w_fds;
472 struct tevent_fd *fde;
473 int selrtn;
475 /* we maybe need to recalculate the maxfd */
476 if (std_ev->maxfd == EVENT_INVALID_MAXFD) {
477 calc_maxfd(std_ev);
480 FD_ZERO(&r_fds);
481 FD_ZERO(&w_fds);
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;
489 if (fde->flags & TEVENT_FD_READ) {
490 FD_SET(fde->fd, &r_fds);
492 if (fde->flags & TEVENT_FD_WRITE) {
493 FD_SET(fde->fd, &w_fds);
497 if (std_ev->ev->signal_events &&
498 tevent_common_check_signal(std_ev->ev)) {
499 return 0;
502 selrtn = select(std_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
504 if (selrtn == -1 && errno == EINTR &&
505 std_ev->ev->signal_events) {
506 tevent_common_check_signal(std_ev->ev);
507 return 0;
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;
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;
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;
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;
544 return 0;
548 do a single event loop using the events defined in ev
550 static int std_event_loop_once(struct tevent_context *ev, const char *location)
552 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
553 struct std_event_context);
554 struct timeval tval;
556 if (ev->signal_events &&
557 tevent_common_check_signal(ev)) {
558 return 0;
561 if (ev->immediate_events &&
562 tevent_common_loop_immediate(ev)) {
563 return 0;
566 tval = tevent_common_loop_timer_delay(ev);
567 if (tevent_timeval_is_zero(&tval)) {
568 return 0;
571 epoll_check_reopen(std_ev);
573 if (epoll_event_loop(std_ev, &tval) == 0) {
574 return 0;
577 return std_event_loop_select(std_ev, &tval);
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,
594 _PRIVATE_ bool tevent_standard_init(void)
596 return tevent_register_backend("standard", &std_event_ops);