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 2 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, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This is SAMBA's default event loop code
25 - we try to use epoll if configure detected support for it
26 otherwise we use select()
27 - if epoll is broken on the system or the kernel doesn't support it
28 at runtime we fallback to select()
32 #include "system/filesys.h"
33 #include "dlinklist.h"
34 #include "lib/events/events.h"
35 #include "lib/events/events_internal.h"
37 struct std_event_context {
38 /* a pointer back to the generic event_context */
39 struct event_context *ev;
41 /* list of filedescriptor events */
42 struct fd_event *fd_events;
44 /* list of timed events */
45 struct timed_event *timed_events;
47 /* the maximum file descriptor number in fd_events */
50 /* information for exiting from the event loop */
53 /* this is changed by the destructors for the fd event
54 type. It is used to detect event destruction by event
55 handlers, which means the code that is calling the event
56 handler needs to assume that the linked list is no longer
59 uint32_t destruction_count;
61 /* when using epoll this is the handle from epoll_create */
65 static void std_event_loop_timer(struct std_event_context *std_ev);
67 /* use epoll if it is available */
70 called when a epoll call fails, and we should fallback
73 static void epoll_fallback_to_select(struct std_event_context *std_ev, const char *reason)
75 DEBUG(0,("%s (%s) - falling back to select()\n", reason, strerror(errno)));
76 close(std_ev->epoll_fd);
77 std_ev->epoll_fd = -1;
78 talloc_set_destructor(std_ev, NULL);
82 map from EVENT_FD_* to EPOLLIN/EPOLLOUT
84 static uint32_t epoll_map_flags(uint16_t flags)
87 if (flags & EVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP);
88 if (flags & EVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP);
95 static int epoll_ctx_destructor(void *ptr)
97 struct std_event_context *std_ev = talloc_get_type(ptr,
98 struct std_event_context);
99 close(std_ev->epoll_fd);
100 std_ev->epoll_fd = -1;
107 static void epoll_init_ctx(struct std_event_context *std_ev, BOOL try_epoll)
109 if (!try_epoll) return;
110 std_ev->epoll_fd = epoll_create(64);
111 talloc_set_destructor(std_ev, epoll_ctx_destructor);
114 #define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT (1<<0)
115 #define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1)
116 #define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2)
119 add the epoll event to the given fd_event
121 static void epoll_add_event(struct std_event_context *std_ev, struct fd_event *fde)
123 struct epoll_event event;
124 if (std_ev->epoll_fd == -1) return;
126 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
128 /* if we don't want events yet, don't add an epoll_event */
129 if (fde->flags == 0) return;
132 event.events = epoll_map_flags(fde->flags);
133 event.data.ptr = fde;
134 if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event) != 0) {
135 epoll_fallback_to_select(std_ev, "EPOLL_CTL_ADD failed");
137 fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
139 /* only if we want to read we want to tell the event handler about errors */
140 if (fde->flags & EVENT_FD_READ) {
141 fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
146 delete the epoll event for given fd_event
148 static void epoll_del_event(struct std_event_context *std_ev, struct fd_event *fde)
150 struct epoll_event event;
151 if (std_ev->epoll_fd == -1) return;
153 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
155 /* if there's no epoll_event, we don't need to delete it */
156 if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT)) return;
159 event.events = epoll_map_flags(fde->flags);
160 event.data.ptr = fde;
161 epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event);
162 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
166 change the epoll event to the given fd_event
168 static void epoll_mod_event(struct std_event_context *std_ev, struct fd_event *fde)
170 struct epoll_event event;
171 if (std_ev->epoll_fd == -1) return;
173 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
176 event.events = epoll_map_flags(fde->flags);
177 event.data.ptr = fde;
178 if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) {
179 epoll_fallback_to_select(std_ev, "EPOLL_CTL_MOD failed");
182 /* only if we want to read we want to tell the event handler about errors */
183 if (fde->flags & EVENT_FD_READ) {
184 fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
188 static void epoll_change_event(struct std_event_context *std_ev, struct fd_event *fde)
190 BOOL got_error = (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR);
191 BOOL want_read = (fde->flags & EVENT_FD_READ);
192 BOOL want_write= (fde->flags & EVENT_FD_WRITE);
194 if (std_ev->epoll_fd == -1) return;
196 fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
198 /* there's already an event */
199 if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT) {
200 if (want_read || (want_write && !got_error)) {
201 epoll_mod_event(std_ev, fde);
205 * if we want to match the select behavior, we need to remove the epoll_event
206 * when the caller isn't interested in events.
208 * this is because epoll reports EPOLLERR and EPOLLHUP, even without asking for them
210 epoll_del_event(std_ev, fde);
214 /* there's no epoll_event attached to the fde */
215 if (want_read || (want_write && !got_error)) {
216 epoll_add_event(std_ev, fde);
222 event loop handling using epoll
224 static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tvalp)
228 struct epoll_event events[MAXEVENTS];
229 uint32_t destruction_count = std_ev->destruction_count;
232 if (std_ev->epoll_fd == -1) return -1;
235 /* it's better to trigger timed events a bit later than to early */
236 timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
239 ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout);
241 if (ret == -1 && errno != EINTR) {
242 epoll_fallback_to_select(std_ev, "epoll_wait() failed");
246 if (ret == 0 && tvalp) {
247 std_event_loop_timer(std_ev);
251 for (i=0;i<ret;i++) {
252 struct fd_event *fde = talloc_get_type(events[i].data.ptr,
257 epoll_fallback_to_select(std_ev, "epoll_wait() gave bad data");
260 if (events[i].events & (EPOLLHUP|EPOLLERR)) {
261 fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR;
263 * if we only wait for EVENT_FD_WRITE, we should not tell the
264 * event handler about it, and remove the epoll_event,
265 * as we only report errors when waiting for read events,
266 * to match the select() behavior
268 if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) {
269 epoll_del_event(std_ev, fde);
272 flags |= EVENT_FD_READ;
274 if (events[i].events & EPOLLIN) flags |= EVENT_FD_READ;
275 if (events[i].events & EPOLLOUT) flags |= EVENT_FD_WRITE;
277 fde->handler(std_ev->ev, fde, flags, fde->private_data);
278 if (destruction_count != std_ev->destruction_count) {
287 #define epoll_init_ctx(std_ev,try_epoll) if (try_epoll) {/* fix unused variable warning*/}
288 #define epoll_add_event(std_ev,fde)
289 #define epoll_del_event(std_ev,fde)
290 #define epoll_change_event(std_ev,fde)
291 #define epoll_event_loop(std_ev,tvalp) (-1)
295 create a std_event_context structure.
297 static int std_event_context_init(struct event_context *ev, void *private_data)
299 struct std_event_context *std_ev;
300 BOOL *_try_epoll = private_data;
301 BOOL try_epoll = (_try_epoll == NULL ? True : *_try_epoll);
303 std_ev = talloc_zero(ev, struct std_event_context);
304 if (!std_ev) return -1;
306 std_ev->epoll_fd = -1;
308 epoll_init_ctx(std_ev, try_epoll);
310 ev->additional_data = std_ev;
315 recalculate the maxfd
317 static void calc_maxfd(struct std_event_context *std_ev)
319 struct fd_event *fde;
322 for (fde = std_ev->fd_events; fde; fde = fde->next) {
323 if (fde->fd > std_ev->maxfd) {
324 std_ev->maxfd = fde->fd;
330 /* to mark the ev->maxfd invalid
331 * this means we need to recalculate it
333 #define EVENT_INVALID_MAXFD (-1)
338 static int std_event_fd_destructor(void *ptr)
340 struct fd_event *fde = talloc_get_type(ptr, struct fd_event);
341 struct event_context *ev = fde->event_ctx;
342 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
343 struct std_event_context);
345 if (std_ev->maxfd == fde->fd) {
346 std_ev->maxfd = EVENT_INVALID_MAXFD;
349 DLIST_REMOVE(std_ev->fd_events, fde);
350 std_ev->destruction_count++;
352 epoll_del_event(std_ev, fde);
359 return NULL on failure (memory allocation error)
361 static struct fd_event *std_event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
362 int fd, uint16_t flags,
363 event_fd_handler_t handler,
366 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
367 struct std_event_context);
368 struct fd_event *fde;
370 fde = talloc(mem_ctx?mem_ctx:ev, struct fd_event);
371 if (!fde) return NULL;
376 fde->handler = handler;
377 fde->private_data = private_data;
378 fde->additional_flags = 0;
379 fde->additional_data = NULL;
381 DLIST_ADD(std_ev->fd_events, fde);
382 if (fde->fd > std_ev->maxfd) {
383 std_ev->maxfd = fde->fd;
385 talloc_set_destructor(fde, std_event_fd_destructor);
387 epoll_add_event(std_ev, fde);
394 return the fd event flags
396 static uint16_t std_event_get_fd_flags(struct fd_event *fde)
402 set the fd event flags
404 static void std_event_set_fd_flags(struct fd_event *fde, uint16_t flags)
406 struct event_context *ev;
407 struct std_event_context *std_ev;
409 if (fde->flags == flags) return;
412 std_ev = talloc_get_type(ev->additional_data, struct std_event_context);
416 epoll_change_event(std_ev, fde);
420 destroy a timed event
422 static int std_event_timed_destructor(void *ptr)
424 struct timed_event *te = talloc_get_type(ptr, struct timed_event);
425 struct std_event_context *std_ev = talloc_get_type(te->event_ctx->additional_data,
426 struct std_event_context);
427 DLIST_REMOVE(std_ev->timed_events, te);
431 static int std_event_timed_deny_destructor(void *ptr)
438 return NULL on failure (memory allocation error)
440 static struct timed_event *std_event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx,
441 struct timeval next_event,
442 event_timed_handler_t handler,
445 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
446 struct std_event_context);
447 struct timed_event *te, *last_te, *cur_te;
449 te = talloc(mem_ctx?mem_ctx:ev, struct timed_event);
450 if (te == NULL) return NULL;
453 te->next_event = next_event;
454 te->handler = handler;
455 te->private_data = private_data;
456 te->additional_data = NULL;
458 /* keep the list ordered */
460 for (cur_te = std_ev->timed_events; cur_te; cur_te = cur_te->next) {
461 /* if the new event comes before the current one break */
462 if (!timeval_is_zero(&cur_te->next_event) &&
463 timeval_compare(&te->next_event,
464 &cur_te->next_event) < 0) {
471 DLIST_ADD_AFTER(std_ev->timed_events, te, last_te);
473 talloc_set_destructor(te, std_event_timed_destructor);
479 a timer has gone off - call it
481 static void std_event_loop_timer(struct std_event_context *std_ev)
483 struct timeval t = timeval_current();
484 struct timed_event *te = std_ev->timed_events;
490 /* deny the handler to free the event */
491 talloc_set_destructor(te, std_event_timed_deny_destructor);
493 /* We need to remove the timer from the list before calling the
494 * handler because in a semi-async inner event loop called from the
495 * handler we don't want to come across this event again -- vl */
496 DLIST_REMOVE(std_ev->timed_events, te);
498 te->handler(std_ev->ev, te, t, te->private_data);
500 /* The destructor isn't necessary anymore, we've already removed the
501 * event from the list. */
502 talloc_set_destructor(te, NULL);
508 event loop handling using select()
510 static int std_event_loop_select(struct std_event_context *std_ev, struct timeval *tvalp)
513 struct fd_event *fde;
515 uint32_t destruction_count = std_ev->destruction_count;
517 /* we maybe need to recalculate the maxfd */
518 if (std_ev->maxfd == EVENT_INVALID_MAXFD) {
525 /* setup any fd events */
526 for (fde = std_ev->fd_events; fde; fde = fde->next) {
527 if (fde->flags & EVENT_FD_READ) {
528 FD_SET(fde->fd, &r_fds);
530 if (fde->flags & EVENT_FD_WRITE) {
531 FD_SET(fde->fd, &w_fds);
535 selrtn = select(std_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
537 if (selrtn == -1 && errno == EBADF) {
538 /* the socket is dead! this should never
539 happen as the socket should have first been
540 made readable and that should have removed
541 the event, so this must be a bug. This is a
543 DEBUG(0,("ERROR: EBADF on std_event_loop_once\n"));
544 std_ev->exit_code = EBADF;
548 if (selrtn == 0 && tvalp) {
549 std_event_loop_timer(std_ev);
554 /* at least one file descriptor is ready - check
555 which ones and call the handler, being careful to allow
556 the handler to remove itself when called */
557 for (fde = std_ev->fd_events; fde; fde = fde->next) {
560 if (FD_ISSET(fde->fd, &r_fds)) flags |= EVENT_FD_READ;
561 if (FD_ISSET(fde->fd, &w_fds)) flags |= EVENT_FD_WRITE;
563 fde->handler(std_ev->ev, fde, flags, fde->private_data);
564 if (destruction_count != std_ev->destruction_count) {
575 do a single event loop using the events defined in ev
577 static int std_event_loop_once(struct event_context *ev)
579 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
580 struct std_event_context);
583 /* work out the right timeout for all timed events */
584 if (std_ev->timed_events) {
585 struct timeval t = timeval_current();
586 tval = timeval_until(&t, &std_ev->timed_events->next_event);
587 if (timeval_is_zero(&tval)) {
588 std_event_loop_timer(std_ev);
592 /* have a default tick time of 30 seconds. This guarantees
593 that code that uses its own timeout checking will be
594 able to proceeed eventually */
595 tval = timeval_set(30, 0);
598 if (epoll_event_loop(std_ev, &tval) == 0) {
602 return std_event_loop_select(std_ev, &tval);
606 return on failure or (with 0) if all fd events are removed
608 static int std_event_loop_wait(struct event_context *ev)
610 struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
611 struct std_event_context);
612 std_ev->exit_code = 0;
614 while (std_ev->fd_events && std_ev->exit_code == 0) {
615 if (std_event_loop_once(ev) != 0) {
620 return std_ev->exit_code;
623 static const struct event_ops std_event_ops = {
624 .context_init = std_event_context_init,
625 .add_fd = std_event_add_fd,
626 .get_fd_flags = std_event_get_fd_flags,
627 .set_fd_flags = std_event_set_fd_flags,
628 .add_timed = std_event_add_timed,
629 .loop_once = std_event_loop_once,
630 .loop_wait = std_event_loop_wait,
633 const struct event_ops *event_standard_get_ops(void)
635 return &std_event_ops;