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
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.
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.
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/>.
22 This is SAMBA's default event loop code
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()
31 #include "system/filesys.h"
32 #include "system/select.h"
34 #include "tevent_util.h"
35 #include "tevent_internal.h"
37 struct std_event_context {
38 /* a pointer back to the generic event_context */
39 struct tevent_context *ev;
41 /* the maximum file descriptor number in fd_events */
44 /* information for exiting from the event loop */
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
53 uint32_t destruction_count;
55 /* when using epoll this is the handle from epoll_create */
58 /* our pid at the time the epoll_fd was created */
62 /* use epoll if it is available */
65 called when a epoll call fails, and we should fallback
68 static void epoll_fallback_to_select(struct std_event_context *std_ev, const char *reason)
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);
79 map from TEVENT_FD_* to EPOLLIN/EPOLLOUT
81 static uint32_t epoll_map_flags(uint16_t flags)
84 if (flags & TEVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP);
85 if (flags & TEVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP);
92 static int epoll_ctx_destructor(struct std_event_context *std_ev)
94 if (std_ev->epoll_fd != -1) {
95 close(std_ev->epoll_fd);
97 std_ev->epoll_fd = -1;
104 static void epoll_init_ctx(struct std_event_context *std_ev)
106 std_ev->epoll_fd = epoll_create(64);
107 std_ev->pid = getpid();
108 talloc_set_destructor(std_ev, epoll_ctx_destructor);
111 static void epoll_add_event(struct std_event_context *std_ev, struct tevent_fd *fde);
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
118 static void epoll_check_reopen(struct std_event_context *std_ev)
120 struct tevent_fd *fde;
122 if (std_ev->pid == getpid()) {
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");
133 std_ev->pid = getpid();
134 for (fde=std_ev->ev->fd_events;fde;fde=fde->next) {
135 epoll_add_event(std_ev, fde);
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)
144 add the epoll event to the given fd_event
146 static void epoll_add_event(struct std_event_context *std_ev, struct tevent_fd *fde)
148 struct epoll_event event;
149 if (std_ev->epoll_fd == -1) return;
151 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
153 /* if we don't want events yet, don't add an epoll_event */
154 if (fde->flags == 0) return;
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");
162 fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
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;
171 delete the epoll event for given fd_event
173 static void epoll_del_event(struct std_event_context *std_ev, struct tevent_fd *fde)
175 struct epoll_event event;
176 if (std_ev->epoll_fd == -1) return;
178 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
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;
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;
191 change the epoll event to the given fd_event
193 static void epoll_mod_event(struct std_event_context *std_ev, struct tevent_fd *fde)
195 struct epoll_event event;
196 if (std_ev->epoll_fd == -1) return;
198 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
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");
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;
213 static void epoll_change_event(struct std_event_context *std_ev, struct tevent_fd *fde)
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);
219 if (std_ev->epoll_fd == -1) return;
221 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
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);
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.
233 * this is because epoll reports EPOLLERR and EPOLLHUP, even without asking for them
235 epoll_del_event(std_ev, fde);
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);
247 event loop handling using epoll
249 static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tvalp)
253 struct epoll_event events[MAXEVENTS];
254 uint32_t destruction_count = ++std_ev->destruction_count;
257 if (std_ev->epoll_fd == -1) return -1;
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);
264 if (std_ev->ev->signal_events &&
265 tevent_common_check_signal(std_ev->ev)) {
269 ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout);
271 if (ret == -1 && errno == EINTR && std_ev->ev->signal_events) {
272 if (tevent_common_check_signal(std_ev->ev)) {
277 if (ret == -1 && errno != EINTR) {
278 epoll_fallback_to_select(std_ev, "epoll_wait() failed");
282 if (ret == 0 && tvalp) {
283 /* we don't care about a possible delay here */
284 tevent_common_loop_timer_delay(std_ev->ev);
288 for (i=0;i<ret;i++) {
289 struct tevent_fd *fde = talloc_get_type(events[i].data.ptr,
294 epoll_fallback_to_select(std_ev, "epoll_wait() gave bad data");
297 if (events[i].events & (EPOLLHUP|EPOLLERR)) {
298 fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR;
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
305 if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) {
306 epoll_del_event(std_ev, fde);
309 flags |= TEVENT_FD_READ;
311 if (events[i].events & EPOLLIN) flags |= TEVENT_FD_READ;
312 if (events[i].events & EPOLLOUT) flags |= TEVENT_FD_WRITE;
314 fde->handler(std_ev->ev, fde, flags, fde->private_data);
315 if (destruction_count != std_ev->destruction_count) {
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)
333 create a std_event_context structure.
335 static int std_event_context_init(struct tevent_context *ev)
337 struct std_event_context *std_ev;
339 std_ev = talloc_zero(ev, struct std_event_context);
340 if (!std_ev) return -1;
342 std_ev->epoll_fd = -1;
344 epoll_init_ctx(std_ev);
346 ev->additional_data = std_ev;
351 recalculate the maxfd
353 static void calc_maxfd(struct std_event_context *std_ev)
355 struct tevent_fd *fde;
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;
366 /* to mark the ev->maxfd invalid
367 * this means we need to recalculate it
369 #define EVENT_INVALID_MAXFD (-1)
374 static int std_event_fd_destructor(struct tevent_fd *fde)
376 struct tevent_context *ev = fde->event_ctx;
377 struct std_event_context *std_ev = NULL;
380 std_ev = talloc_get_type(ev->additional_data,
381 struct std_event_context);
383 epoll_check_reopen(std_ev);
385 if (std_ev->maxfd == fde->fd) {
386 std_ev->maxfd = EVENT_INVALID_MAXFD;
389 std_ev->destruction_count++;
391 epoll_del_event(std_ev, fde);
394 return tevent_common_fd_destructor(fde);
399 return NULL on failure (memory allocation error)
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,
405 const char *handler_name,
406 const char *location)
408 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
409 struct std_event_context);
410 struct tevent_fd *fde;
412 epoll_check_reopen(std_ev);
414 fde = tevent_common_add_fd(ev, mem_ctx, fd, flags,
415 handler, private_data,
416 handler_name, location);
417 if (!fde) return NULL;
419 if ((std_ev->maxfd != EVENT_INVALID_MAXFD)
420 && (fde->fd > std_ev->maxfd)) {
421 std_ev->maxfd = fde->fd;
423 talloc_set_destructor(fde, std_event_fd_destructor);
425 epoll_add_event(std_ev, fde);
431 set the fd event flags
433 static void std_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
435 struct tevent_context *ev;
436 struct std_event_context *std_ev;
438 if (fde->flags == flags) return;
441 std_ev = talloc_get_type(ev->additional_data, struct std_event_context);
445 epoll_check_reopen(std_ev);
447 epoll_change_event(std_ev, fde);
451 event loop handling using select()
453 static int std_event_loop_select(struct std_event_context *std_ev, struct timeval *tvalp)
456 struct tevent_fd *fde;
458 uint32_t destruction_count = ++std_ev->destruction_count;
460 /* we maybe need to recalculate the maxfd */
461 if (std_ev->maxfd == EVENT_INVALID_MAXFD) {
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);
473 if (fde->flags & TEVENT_FD_WRITE) {
474 FD_SET(fde->fd, &w_fds);
478 if (std_ev->ev->signal_events &&
479 tevent_common_check_signal(std_ev->ev)) {
483 selrtn = select(std_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
485 if (selrtn == -1 && errno == EINTR &&
486 std_ev->ev->signal_events) {
487 tevent_common_check_signal(std_ev->ev);
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
497 tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
498 "ERROR: EBADF on std_event_loop_once\n");
499 std_ev->exit_code = EBADF;
503 if (selrtn == 0 && tvalp) {
504 /* we don't care about a possible delay here */
505 tevent_common_loop_timer_delay(std_ev->ev);
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) {
516 if (FD_ISSET(fde->fd, &r_fds)) flags |= TEVENT_FD_READ;
517 if (FD_ISSET(fde->fd, &w_fds)) flags |= TEVENT_FD_WRITE;
519 fde->handler(std_ev->ev, fde, flags, fde->private_data);
520 if (destruction_count != std_ev->destruction_count) {
531 do a single event loop using the events defined in ev
533 static int std_event_loop_once(struct tevent_context *ev)
535 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
536 struct std_event_context);
539 tval = tevent_common_loop_timer_delay(ev);
540 if (ev_timeval_is_zero(&tval)) {
544 epoll_check_reopen(std_ev);
546 if (epoll_event_loop(std_ev, &tval) == 0) {
550 return std_event_loop_select(std_ev, &tval);
554 return on failure or (with 0) if all fd events are removed
556 static int std_event_loop_wait(struct tevent_context *ev)
558 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
559 struct std_event_context);
560 std_ev->exit_code = 0;
562 while (ev->fd_events && std_ev->exit_code == 0) {
563 if (std_event_loop_once(ev) != 0) {
568 return std_ev->exit_code;
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,
584 bool tevent_standard_init(void)
586 return tevent_register_backend("standard", &std_event_ops);