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
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 <ccan/tevent/tevent.h>
35 #include <ccan/tevent/tevent_internal.h>
36 #include <ccan/tevent/tevent_util.h>
39 struct std_event_context {
40 /* a pointer back to the generic event_context */
41 struct tevent_context *ev;
43 /* the maximum file descriptor number in fd_events */
46 /* information for exiting from the event loop */
49 /* when using epoll this is the handle from epoll_create */
52 /* our pid at the time the epoll_fd was created */
56 /* use epoll if it is available */
59 called when a epoll call fails, and we should fallback
62 static void epoll_fallback_to_select(struct std_event_context *std_ev, const char *reason)
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);
73 map from TEVENT_FD_* to EPOLLIN/EPOLLOUT
75 static uint32_t epoll_map_flags(uint16_t flags)
78 if (flags & TEVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP);
79 if (flags & TEVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP);
86 static int epoll_ctx_destructor(struct std_event_context *std_ev)
88 if (std_ev->epoll_fd != -1) {
89 close(std_ev->epoll_fd);
91 std_ev->epoll_fd = -1;
98 static void epoll_init_ctx(struct std_event_context *std_ev)
100 std_ev->epoll_fd = epoll_create(64);
101 std_ev->pid = getpid();
102 talloc_set_destructor(std_ev, epoll_ctx_destructor);
105 static void epoll_add_event(struct std_event_context *std_ev, struct tevent_fd *fde);
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
112 static void epoll_check_reopen(struct std_event_context *std_ev)
114 struct tevent_fd *fde;
116 if (std_ev->pid == getpid()) {
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");
127 std_ev->pid = getpid();
128 for (fde=std_ev->ev->fd_events;fde;fde=fde->next) {
129 epoll_add_event(std_ev, fde);
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)
138 add the epoll event to the given fd_event
140 static void epoll_add_event(struct std_event_context *std_ev, struct tevent_fd *fde)
142 struct epoll_event event;
143 if (std_ev->epoll_fd == -1) return;
145 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
147 /* if we don't want events yet, don't add an epoll_event */
148 if (fde->flags == 0) return;
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");
156 fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
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;
165 delete the epoll event for given fd_event
167 static void epoll_del_event(struct std_event_context *std_ev, struct tevent_fd *fde)
169 struct epoll_event event;
170 if (std_ev->epoll_fd == -1) return;
172 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
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;
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;
185 change the epoll event to the given fd_event
187 static void epoll_mod_event(struct std_event_context *std_ev, struct tevent_fd *fde)
189 struct epoll_event event;
190 if (std_ev->epoll_fd == -1) return;
192 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
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");
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;
207 static void epoll_change_event(struct std_event_context *std_ev, struct tevent_fd *fde)
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);
213 if (std_ev->epoll_fd == -1) return;
215 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
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);
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.
227 * this is because epoll reports EPOLLERR and EPOLLHUP, even without asking for them
229 epoll_del_event(std_ev, fde);
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);
241 event loop handling using epoll
243 static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tvalp)
247 struct epoll_event events[MAXEVENTS];
250 if (std_ev->epoll_fd == -1) return -1;
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);
257 if (std_ev->ev->signal_events &&
258 tevent_common_check_signal(std_ev->ev)) {
262 ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout);
264 if (ret == -1 && errno == EINTR && std_ev->ev->signal_events) {
265 if (tevent_common_check_signal(std_ev->ev)) {
270 if (ret == -1 && errno != EINTR) {
271 epoll_fallback_to_select(std_ev, "epoll_wait() failed");
275 if (ret == 0 && tvalp) {
276 /* we don't care about a possible delay here */
277 tevent_common_loop_timer_delay(std_ev->ev);
281 for (i=0;i<ret;i++) {
282 struct tevent_fd *fde = talloc_get_type(events[i].data.ptr,
287 epoll_fallback_to_select(std_ev, "epoll_wait() gave bad data");
290 if (events[i].events & (EPOLLHUP|EPOLLERR)) {
291 fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR;
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
298 if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) {
299 epoll_del_event(std_ev, fde);
302 flags |= TEVENT_FD_READ;
304 if (events[i].events & EPOLLIN) flags |= TEVENT_FD_READ;
305 if (events[i].events & EPOLLOUT) flags |= TEVENT_FD_WRITE;
307 fde->handler(std_ev->ev, fde, flags, fde->private_data);
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)
324 create a std_event_context structure.
326 static int std_event_context_init(struct tevent_context *ev)
328 struct std_event_context *std_ev;
330 std_ev = talloc_zero(ev, struct std_event_context);
331 if (!std_ev) return -1;
333 std_ev->epoll_fd = -1;
335 epoll_init_ctx(std_ev);
337 ev->additional_data = std_ev;
342 recalculate the maxfd
344 static void calc_maxfd(struct std_event_context *std_ev)
346 struct tevent_fd *fde;
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;
357 /* to mark the ev->maxfd invalid
358 * this means we need to recalculate it
360 #define EVENT_INVALID_MAXFD (-1)
365 static int std_event_fd_destructor(struct tevent_fd *fde)
367 struct tevent_context *ev = fde->event_ctx;
368 struct std_event_context *std_ev = NULL;
371 std_ev = talloc_get_type(ev->additional_data,
372 struct std_event_context);
374 epoll_check_reopen(std_ev);
376 if (std_ev->maxfd == fde->fd) {
377 std_ev->maxfd = EVENT_INVALID_MAXFD;
380 epoll_del_event(std_ev, fde);
383 return tevent_common_fd_destructor(fde);
388 return NULL on failure (memory allocation error)
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,
394 const char *handler_name,
395 const char *location)
397 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
398 struct std_event_context);
399 struct tevent_fd *fde;
401 epoll_check_reopen(std_ev);
403 fde = tevent_common_add_fd(ev, mem_ctx, fd, flags,
404 handler, private_data,
405 handler_name, location);
406 if (!fde) return NULL;
408 if ((std_ev->maxfd != EVENT_INVALID_MAXFD)
409 && (fde->fd > std_ev->maxfd)) {
410 std_ev->maxfd = fde->fd;
412 talloc_set_destructor(fde, std_event_fd_destructor);
414 epoll_add_event(std_ev, fde);
420 set the fd event flags
422 static void std_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
424 struct tevent_context *ev;
425 struct std_event_context *std_ev;
427 if (fde->flags == flags) return;
430 std_ev = talloc_get_type(ev->additional_data, struct std_event_context);
434 epoll_check_reopen(std_ev);
436 epoll_change_event(std_ev, fde);
440 event loop handling using select()
442 static int std_event_loop_select(struct std_event_context *std_ev, struct timeval *tvalp)
445 struct tevent_fd *fde;
448 /* we maybe need to recalculate the maxfd */
449 if (std_ev->maxfd == EVENT_INVALID_MAXFD) {
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);
461 if (fde->flags & TEVENT_FD_WRITE) {
462 FD_SET(fde->fd, &w_fds);
466 if (std_ev->ev->signal_events &&
467 tevent_common_check_signal(std_ev->ev)) {
471 selrtn = select(std_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
473 if (selrtn == -1 && errno == EINTR &&
474 std_ev->ev->signal_events) {
475 tevent_common_check_signal(std_ev->ev);
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
485 tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
486 "ERROR: EBADF on std_event_loop_once\n");
487 std_ev->exit_code = EBADF;
491 if (selrtn == 0 && tvalp) {
492 /* we don't care about a possible delay here */
493 tevent_common_loop_timer_delay(std_ev->ev);
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) {
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);
517 do a single event loop using the events defined in ev
519 static int std_event_loop_once(struct tevent_context *ev, const char *location)
521 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
522 struct std_event_context);
525 if (ev->signal_events &&
526 tevent_common_check_signal(ev)) {
530 if (ev->immediate_events &&
531 tevent_common_loop_immediate(ev)) {
535 tval = tevent_common_loop_timer_delay(ev);
536 if (tevent_timeval_is_zero(&tval)) {
540 epoll_check_reopen(std_ev);
542 if (epoll_event_loop(std_ev, &tval) == 0) {
546 return std_event_loop_select(std_ev, &tval);
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,
563 _PRIVATE_ bool tevent_standard_init(void)
565 return tevent_register_backend("standard", &std_event_ops);