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()
35 #include "system/filesys.h"
36 #include "system/select.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 */
48 /* information for exiting from the event loop */
51 /* when using epoll this is the handle from epoll_create */
54 /* our pid at the time the epoll_fd was created */
58 /* use epoll if it is available */
61 called when a epoll call fails, and we should fallback
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)
80 if (flags & TEVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP);
81 if (flags & TEVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP);
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;
100 static void epoll_init_ctx(struct std_event_context *std_ev)
102 std_ev->epoll_fd = epoll_create(64);
103 std_ev->pid = getpid();
104 talloc_set_destructor(std_ev, epoll_ctx_destructor);
107 static void epoll_add_event(struct std_event_context *std_ev, struct tevent_fd *fde);
110 reopen the epoll handle when our pid changes
111 see http://junkcode.samba.org/ftp/unpacked/junkcode/epoll_fork.c for an
112 demonstration of why this is needed
114 static void epoll_check_reopen(struct std_event_context *std_ev)
116 struct tevent_fd *fde;
118 if (std_ev->pid == getpid()) {
122 close(std_ev->epoll_fd);
123 std_ev->epoll_fd = epoll_create(64);
124 if (std_ev->epoll_fd == -1) {
125 tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
126 "Failed to recreate epoll handle after fork\n");
129 std_ev->pid = getpid();
130 for (fde=std_ev->ev->fd_events;fde;fde=fde->next) {
131 epoll_add_event(std_ev, fde);
135 #define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT (1<<0)
136 #define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1)
137 #define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2)
140 add the epoll event to the given fd_event
142 static void epoll_add_event(struct std_event_context *std_ev, struct tevent_fd *fde)
144 struct epoll_event event;
145 if (std_ev->epoll_fd == -1) return;
147 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
149 /* if we don't want events yet, don't add an epoll_event */
150 if (fde->flags == 0) return;
153 event.events = epoll_map_flags(fde->flags);
154 event.data.ptr = fde;
155 if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event) != 0) {
156 epoll_fallback_to_select(std_ev, "EPOLL_CTL_ADD failed");
158 fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
160 /* only if we want to read we want to tell the event handler about errors */
161 if (fde->flags & TEVENT_FD_READ) {
162 fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
167 delete the epoll event for given fd_event
169 static void epoll_del_event(struct std_event_context *std_ev, struct tevent_fd *fde)
171 struct epoll_event event;
172 if (std_ev->epoll_fd == -1) return;
174 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
176 /* if there's no epoll_event, we don't need to delete it */
177 if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT)) return;
180 event.events = epoll_map_flags(fde->flags);
181 event.data.ptr = fde;
182 epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event);
183 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
187 change the epoll event to the given fd_event
189 static void epoll_mod_event(struct std_event_context *std_ev, struct tevent_fd *fde)
191 struct epoll_event event;
192 if (std_ev->epoll_fd == -1) return;
194 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
197 event.events = epoll_map_flags(fde->flags);
198 event.data.ptr = fde;
199 if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) {
200 epoll_fallback_to_select(std_ev, "EPOLL_CTL_MOD failed");
203 /* only if we want to read we want to tell the event handler about errors */
204 if (fde->flags & TEVENT_FD_READ) {
205 fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
209 static void epoll_change_event(struct std_event_context *std_ev, struct tevent_fd *fde)
211 bool got_error = (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR);
212 bool want_read = (fde->flags & TEVENT_FD_READ);
213 bool want_write= (fde->flags & TEVENT_FD_WRITE);
215 if (std_ev->epoll_fd == -1) return;
217 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
219 /* there's already an event */
220 if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT) {
221 if (want_read || (want_write && !got_error)) {
222 epoll_mod_event(std_ev, fde);
226 * if we want to match the select behavior, we need to remove the epoll_event
227 * when the caller isn't interested in events.
229 * this is because epoll reports EPOLLERR and EPOLLHUP, even without asking for them
231 epoll_del_event(std_ev, fde);
235 /* there's no epoll_event attached to the fde */
236 if (want_read || (want_write && !got_error)) {
237 epoll_add_event(std_ev, fde);
242 extern pid_t ctdbd_pid;
245 event loop handling using epoll
247 static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tvalp)
251 struct epoll_event events[MAXEVENTS];
254 if (std_ev->epoll_fd == -1) return -1;
257 /* it's better to trigger timed events a bit later than to early */
258 timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
261 if (std_ev->ev->signal_events &&
262 tevent_common_check_signal(std_ev->ev)) {
266 if (getpid() == ctdbd_pid) tevent_before_wait(std_ev->ev);
267 ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout);
268 if (getpid() == ctdbd_pid) tevent_after_wait(std_ev->ev);
270 if (ret == -1 && errno == EINTR && std_ev->ev->signal_events) {
271 if (tevent_common_check_signal(std_ev->ev)) {
276 if (ret == -1 && errno != EINTR) {
277 epoll_fallback_to_select(std_ev, "epoll_wait() failed");
281 if (ret == 0 && tvalp) {
282 /* we don't care about a possible delay here */
283 tevent_common_loop_timer_delay(std_ev->ev);
287 for (i=0;i<ret;i++) {
288 struct tevent_fd *fde = talloc_get_type(events[i].data.ptr,
293 epoll_fallback_to_select(std_ev, "epoll_wait() gave bad data");
296 if (events[i].events & (EPOLLHUP|EPOLLERR)) {
297 fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR;
299 * if we only wait for TEVENT_FD_WRITE, we should not tell the
300 * event handler about it, and remove the epoll_event,
301 * as we only report errors when waiting for read events,
302 * to match the select() behavior
304 if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) {
305 epoll_del_event(std_ev, fde);
308 flags |= TEVENT_FD_READ;
310 if (events[i].events & EPOLLIN) flags |= TEVENT_FD_READ;
311 if (events[i].events & EPOLLOUT) flags |= TEVENT_FD_WRITE;
313 fde->handler(std_ev->ev, fde, flags, fde->private_data);
321 #define epoll_init_ctx(std_ev)
322 #define epoll_add_event(std_ev,fde)
323 #define epoll_del_event(std_ev,fde)
324 #define epoll_change_event(std_ev,fde)
325 #define epoll_event_loop(std_ev,tvalp) (-1)
326 #define epoll_check_reopen(std_ev)
330 create a std_event_context structure.
332 static int std_event_context_init(struct tevent_context *ev)
334 struct std_event_context *std_ev;
336 std_ev = talloc_zero(ev, struct std_event_context);
337 if (!std_ev) return -1;
339 std_ev->epoll_fd = -1;
341 epoll_init_ctx(std_ev);
343 ev->additional_data = std_ev;
348 recalculate the maxfd
350 static void calc_maxfd(struct std_event_context *std_ev)
352 struct tevent_fd *fde;
355 for (fde = std_ev->ev->fd_events; fde; fde = fde->next) {
356 if (fde->fd > std_ev->maxfd) {
357 std_ev->maxfd = fde->fd;
363 /* to mark the ev->maxfd invalid
364 * this means we need to recalculate it
366 #define EVENT_INVALID_MAXFD (-1)
371 static int std_event_fd_destructor(struct tevent_fd *fde)
373 struct tevent_context *ev = fde->event_ctx;
374 struct std_event_context *std_ev = NULL;
377 std_ev = talloc_get_type(ev->additional_data,
378 struct std_event_context);
380 epoll_check_reopen(std_ev);
382 if (std_ev->maxfd == fde->fd) {
383 std_ev->maxfd = EVENT_INVALID_MAXFD;
386 epoll_del_event(std_ev, fde);
389 return tevent_common_fd_destructor(fde);
394 return NULL on failure (memory allocation error)
396 static struct tevent_fd *std_event_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx,
397 int fd, uint16_t flags,
398 tevent_fd_handler_t handler,
400 const char *handler_name,
401 const char *location)
403 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
404 struct std_event_context);
405 struct tevent_fd *fde;
407 epoll_check_reopen(std_ev);
409 fde = tevent_common_add_fd(ev, mem_ctx, fd, flags,
410 handler, private_data,
411 handler_name, location);
412 if (!fde) return NULL;
414 if ((std_ev->maxfd != EVENT_INVALID_MAXFD)
415 && (fde->fd > std_ev->maxfd)) {
416 std_ev->maxfd = fde->fd;
418 talloc_set_destructor(fde, std_event_fd_destructor);
420 epoll_add_event(std_ev, fde);
426 set the fd event flags
428 static void std_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
430 struct tevent_context *ev;
431 struct std_event_context *std_ev;
433 if (fde->flags == flags) return;
436 std_ev = talloc_get_type(ev->additional_data, struct std_event_context);
440 epoll_check_reopen(std_ev);
442 epoll_change_event(std_ev, fde);
446 event loop handling using select()
448 static int std_event_loop_select(struct std_event_context *std_ev, struct timeval *tvalp)
451 struct tevent_fd *fde;
454 /* we maybe need to recalculate the maxfd */
455 if (std_ev->maxfd == EVENT_INVALID_MAXFD) {
462 /* setup any fd events */
463 for (fde = std_ev->ev->fd_events; fde; fde = fde->next) {
464 if (fde->flags & TEVENT_FD_READ) {
465 FD_SET(fde->fd, &r_fds);
467 if (fde->flags & TEVENT_FD_WRITE) {
468 FD_SET(fde->fd, &w_fds);
472 if (std_ev->ev->signal_events &&
473 tevent_common_check_signal(std_ev->ev)) {
477 selrtn = select(std_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
479 if (selrtn == -1 && errno == EINTR &&
480 std_ev->ev->signal_events) {
481 tevent_common_check_signal(std_ev->ev);
485 if (selrtn == -1 && errno == EBADF) {
486 /* the socket is dead! this should never
487 happen as the socket should have first been
488 made readable and that should have removed
489 the event, so this must be a bug. This is a
491 tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
492 "ERROR: EBADF on std_event_loop_once\n");
493 std_ev->exit_code = EBADF;
497 if (selrtn == 0 && tvalp) {
498 /* we don't care about a possible delay here */
499 tevent_common_loop_timer_delay(std_ev->ev);
504 /* at least one file descriptor is ready - check
505 which ones and call the handler, being careful to allow
506 the handler to remove itself when called */
507 for (fde = std_ev->ev->fd_events; fde; fde = fde->next) {
510 if (FD_ISSET(fde->fd, &r_fds)) flags |= TEVENT_FD_READ;
511 if (FD_ISSET(fde->fd, &w_fds)) flags |= TEVENT_FD_WRITE;
513 fde->handler(std_ev->ev, fde, flags, fde->private_data);
523 do a single event loop using the events defined in ev
525 static int std_event_loop_once(struct tevent_context *ev, const char *location)
527 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
528 struct std_event_context);
531 if (ev->signal_events &&
532 tevent_common_check_signal(ev)) {
536 if (ev->immediate_events &&
537 tevent_common_loop_immediate(ev)) {
541 tval = tevent_common_loop_timer_delay(ev);
542 if (tevent_timeval_is_zero(&tval)) {
546 epoll_check_reopen(std_ev);
548 if (epoll_event_loop(std_ev, &tval) == 0) {
552 return std_event_loop_select(std_ev, &tval);
555 static const struct tevent_ops std_event_ops = {
556 .context_init = std_event_context_init,
557 .add_fd = std_event_add_fd,
558 .set_fd_close_fn = tevent_common_fd_set_close_fn,
559 .get_fd_flags = tevent_common_fd_get_flags,
560 .set_fd_flags = std_event_set_fd_flags,
561 .add_timer = tevent_common_add_timer,
562 .schedule_immediate = tevent_common_schedule_immediate,
563 .add_signal = tevent_common_add_signal,
564 .loop_once = std_event_loop_once,
565 .loop_wait = tevent_common_loop_wait,
569 _PRIVATE_ bool tevent_standard_init(void)
571 return tevent_register_backend("standard", &std_event_ops);