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 /* this is changed by the destructors for the fd event
52 type. It is used to detect event destruction by event
53 handlers, which means the code that is calling the event
54 handler needs to assume that the linked list is no longer
57 uint32_t destruction_count
;
59 /* when using epoll this is the handle from epoll_create */
62 /* our pid at the time the epoll_fd was created */
66 /* use epoll if it is available */
69 called when a epoll call fails, and we should fallback
72 static void epoll_fallback_to_select(struct std_event_context
*std_ev
, const char *reason
)
74 tevent_debug(std_ev
->ev
, TEVENT_DEBUG_FATAL
,
75 "%s (%s) - falling back to select()\n",
76 reason
, strerror(errno
));
77 close(std_ev
->epoll_fd
);
78 std_ev
->epoll_fd
= -1;
79 talloc_set_destructor(std_ev
, NULL
);
83 map from TEVENT_FD_* to EPOLLIN/EPOLLOUT
85 static uint32_t epoll_map_flags(uint16_t flags
)
88 if (flags
& TEVENT_FD_READ
) ret
|= (EPOLLIN
| EPOLLERR
| EPOLLHUP
);
89 if (flags
& TEVENT_FD_WRITE
) ret
|= (EPOLLOUT
| EPOLLERR
| EPOLLHUP
);
96 static int epoll_ctx_destructor(struct std_event_context
*std_ev
)
98 if (std_ev
->epoll_fd
!= -1) {
99 close(std_ev
->epoll_fd
);
101 std_ev
->epoll_fd
= -1;
108 static void epoll_init_ctx(struct std_event_context
*std_ev
)
110 std_ev
->epoll_fd
= epoll_create(64);
111 std_ev
->pid
= getpid();
112 talloc_set_destructor(std_ev
, epoll_ctx_destructor
);
115 static void epoll_add_event(struct std_event_context
*std_ev
, struct tevent_fd
*fde
);
118 reopen the epoll handle when our pid changes
119 see http://junkcode.samba.org/ftp/unpacked/junkcode/epoll_fork.c for an
120 demonstration of why this is needed
122 static void epoll_check_reopen(struct std_event_context
*std_ev
)
124 struct tevent_fd
*fde
;
126 if (std_ev
->pid
== getpid()) {
130 close(std_ev
->epoll_fd
);
131 std_ev
->epoll_fd
= epoll_create(64);
132 if (std_ev
->epoll_fd
== -1) {
133 tevent_debug(std_ev
->ev
, TEVENT_DEBUG_FATAL
,
134 "Failed to recreate epoll handle after fork\n");
137 std_ev
->pid
= getpid();
138 for (fde
=std_ev
->ev
->fd_events
;fde
;fde
=fde
->next
) {
139 epoll_add_event(std_ev
, fde
);
143 #define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT (1<<0)
144 #define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1)
145 #define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2)
148 add the epoll event to the given fd_event
150 static void epoll_add_event(struct std_event_context
*std_ev
, struct tevent_fd
*fde
)
152 struct epoll_event event
;
153 if (std_ev
->epoll_fd
== -1) return;
155 fde
->additional_flags
&= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR
;
157 /* if we don't want events yet, don't add an epoll_event */
158 if (fde
->flags
== 0) return;
161 event
.events
= epoll_map_flags(fde
->flags
);
162 event
.data
.ptr
= fde
;
163 if (epoll_ctl(std_ev
->epoll_fd
, EPOLL_CTL_ADD
, fde
->fd
, &event
) != 0) {
164 epoll_fallback_to_select(std_ev
, "EPOLL_CTL_ADD failed");
166 fde
->additional_flags
|= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT
;
168 /* only if we want to read we want to tell the event handler about errors */
169 if (fde
->flags
& TEVENT_FD_READ
) {
170 fde
->additional_flags
|= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR
;
175 delete the epoll event for given fd_event
177 static void epoll_del_event(struct std_event_context
*std_ev
, struct tevent_fd
*fde
)
179 struct epoll_event event
;
180 if (std_ev
->epoll_fd
== -1) return;
182 fde
->additional_flags
&= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR
;
184 /* if there's no epoll_event, we don't need to delete it */
185 if (!(fde
->additional_flags
& EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT
)) return;
188 event
.events
= epoll_map_flags(fde
->flags
);
189 event
.data
.ptr
= fde
;
190 epoll_ctl(std_ev
->epoll_fd
, EPOLL_CTL_DEL
, fde
->fd
, &event
);
191 fde
->additional_flags
&= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT
;
195 change the epoll event to the given fd_event
197 static void epoll_mod_event(struct std_event_context
*std_ev
, struct tevent_fd
*fde
)
199 struct epoll_event event
;
200 if (std_ev
->epoll_fd
== -1) return;
202 fde
->additional_flags
&= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR
;
205 event
.events
= epoll_map_flags(fde
->flags
);
206 event
.data
.ptr
= fde
;
207 if (epoll_ctl(std_ev
->epoll_fd
, EPOLL_CTL_MOD
, fde
->fd
, &event
) != 0) {
208 epoll_fallback_to_select(std_ev
, "EPOLL_CTL_MOD failed");
211 /* only if we want to read we want to tell the event handler about errors */
212 if (fde
->flags
& TEVENT_FD_READ
) {
213 fde
->additional_flags
|= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR
;
217 static void epoll_change_event(struct std_event_context
*std_ev
, struct tevent_fd
*fde
)
219 bool got_error
= (fde
->additional_flags
& EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR
);
220 bool want_read
= (fde
->flags
& TEVENT_FD_READ
);
221 bool want_write
= (fde
->flags
& TEVENT_FD_WRITE
);
223 if (std_ev
->epoll_fd
== -1) return;
225 fde
->additional_flags
&= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR
;
227 /* there's already an event */
228 if (fde
->additional_flags
& EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT
) {
229 if (want_read
|| (want_write
&& !got_error
)) {
230 epoll_mod_event(std_ev
, fde
);
234 * if we want to match the select behavior, we need to remove the epoll_event
235 * when the caller isn't interested in events.
237 * this is because epoll reports EPOLLERR and EPOLLHUP, even without asking for them
239 epoll_del_event(std_ev
, fde
);
243 /* there's no epoll_event attached to the fde */
244 if (want_read
|| (want_write
&& !got_error
)) {
245 epoll_add_event(std_ev
, fde
);
251 event loop handling using epoll
253 static int epoll_event_loop(struct std_event_context
*std_ev
, struct timeval
*tvalp
)
257 struct epoll_event events
[MAXEVENTS
];
258 uint32_t destruction_count
= ++std_ev
->destruction_count
;
261 if (std_ev
->epoll_fd
== -1) return -1;
264 /* it's better to trigger timed events a bit later than to early */
265 timeout
= ((tvalp
->tv_usec
+999) / 1000) + (tvalp
->tv_sec
*1000);
268 if (std_ev
->ev
->signal_events
&&
269 tevent_common_check_signal(std_ev
->ev
)) {
273 ret
= epoll_wait(std_ev
->epoll_fd
, events
, MAXEVENTS
, timeout
);
275 if (ret
== -1 && errno
== EINTR
&& std_ev
->ev
->signal_events
) {
276 if (tevent_common_check_signal(std_ev
->ev
)) {
281 if (ret
== -1 && errno
!= EINTR
) {
282 epoll_fallback_to_select(std_ev
, "epoll_wait() failed");
286 if (ret
== 0 && tvalp
) {
287 /* we don't care about a possible delay here */
288 tevent_common_loop_timer_delay(std_ev
->ev
);
292 for (i
=0;i
<ret
;i
++) {
293 struct tevent_fd
*fde
= talloc_get_type(events
[i
].data
.ptr
,
298 epoll_fallback_to_select(std_ev
, "epoll_wait() gave bad data");
301 if (events
[i
].events
& (EPOLLHUP
|EPOLLERR
)) {
302 fde
->additional_flags
|= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR
;
304 * if we only wait for TEVENT_FD_WRITE, we should not tell the
305 * event handler about it, and remove the epoll_event,
306 * as we only report errors when waiting for read events,
307 * to match the select() behavior
309 if (!(fde
->additional_flags
& EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR
)) {
310 epoll_del_event(std_ev
, fde
);
313 flags
|= TEVENT_FD_READ
;
315 if (events
[i
].events
& EPOLLIN
) flags
|= TEVENT_FD_READ
;
316 if (events
[i
].events
& EPOLLOUT
) flags
|= TEVENT_FD_WRITE
;
318 fde
->handler(std_ev
->ev
, fde
, flags
, fde
->private_data
);
319 if (destruction_count
!= std_ev
->destruction_count
) {
328 #define epoll_init_ctx(std_ev)
329 #define epoll_add_event(std_ev,fde)
330 #define epoll_del_event(std_ev,fde)
331 #define epoll_change_event(std_ev,fde)
332 #define epoll_event_loop(std_ev,tvalp) (-1)
333 #define epoll_check_reopen(std_ev)
337 create a std_event_context structure.
339 static int std_event_context_init(struct tevent_context
*ev
)
341 struct std_event_context
*std_ev
;
343 std_ev
= talloc_zero(ev
, struct std_event_context
);
344 if (!std_ev
) return -1;
346 std_ev
->epoll_fd
= -1;
348 epoll_init_ctx(std_ev
);
350 ev
->additional_data
= std_ev
;
355 recalculate the maxfd
357 static void calc_maxfd(struct std_event_context
*std_ev
)
359 struct tevent_fd
*fde
;
362 for (fde
= std_ev
->ev
->fd_events
; fde
; fde
= fde
->next
) {
363 if (fde
->fd
> std_ev
->maxfd
) {
364 std_ev
->maxfd
= fde
->fd
;
370 /* to mark the ev->maxfd invalid
371 * this means we need to recalculate it
373 #define EVENT_INVALID_MAXFD (-1)
378 static int std_event_fd_destructor(struct tevent_fd
*fde
)
380 struct tevent_context
*ev
= fde
->event_ctx
;
381 struct std_event_context
*std_ev
= NULL
;
384 std_ev
= talloc_get_type(ev
->additional_data
,
385 struct std_event_context
);
387 epoll_check_reopen(std_ev
);
389 if (std_ev
->maxfd
== fde
->fd
) {
390 std_ev
->maxfd
= EVENT_INVALID_MAXFD
;
393 std_ev
->destruction_count
++;
395 epoll_del_event(std_ev
, fde
);
398 return tevent_common_fd_destructor(fde
);
403 return NULL on failure (memory allocation error)
405 static struct tevent_fd
*std_event_add_fd(struct tevent_context
*ev
, TALLOC_CTX
*mem_ctx
,
406 int fd
, uint16_t flags
,
407 tevent_fd_handler_t handler
,
409 const char *handler_name
,
410 const char *location
)
412 struct std_event_context
*std_ev
= talloc_get_type(ev
->additional_data
,
413 struct std_event_context
);
414 struct tevent_fd
*fde
;
416 epoll_check_reopen(std_ev
);
418 fde
= tevent_common_add_fd(ev
, mem_ctx
, fd
, flags
,
419 handler
, private_data
,
420 handler_name
, location
);
421 if (!fde
) return NULL
;
423 if ((std_ev
->maxfd
!= EVENT_INVALID_MAXFD
)
424 && (fde
->fd
> std_ev
->maxfd
)) {
425 std_ev
->maxfd
= fde
->fd
;
427 talloc_set_destructor(fde
, std_event_fd_destructor
);
429 epoll_add_event(std_ev
, fde
);
435 set the fd event flags
437 static void std_event_set_fd_flags(struct tevent_fd
*fde
, uint16_t flags
)
439 struct tevent_context
*ev
;
440 struct std_event_context
*std_ev
;
442 if (fde
->flags
== flags
) return;
445 std_ev
= talloc_get_type(ev
->additional_data
, struct std_event_context
);
449 epoll_check_reopen(std_ev
);
451 epoll_change_event(std_ev
, fde
);
455 event loop handling using select()
457 static int std_event_loop_select(struct std_event_context
*std_ev
, struct timeval
*tvalp
)
460 struct tevent_fd
*fde
;
462 uint32_t destruction_count
= ++std_ev
->destruction_count
;
464 /* we maybe need to recalculate the maxfd */
465 if (std_ev
->maxfd
== EVENT_INVALID_MAXFD
) {
472 /* setup any fd events */
473 for (fde
= std_ev
->ev
->fd_events
; fde
; fde
= fde
->next
) {
474 if (fde
->flags
& TEVENT_FD_READ
) {
475 FD_SET(fde
->fd
, &r_fds
);
477 if (fde
->flags
& TEVENT_FD_WRITE
) {
478 FD_SET(fde
->fd
, &w_fds
);
482 if (std_ev
->ev
->signal_events
&&
483 tevent_common_check_signal(std_ev
->ev
)) {
487 selrtn
= select(std_ev
->maxfd
+1, &r_fds
, &w_fds
, NULL
, tvalp
);
489 if (selrtn
== -1 && errno
== EINTR
&&
490 std_ev
->ev
->signal_events
) {
491 tevent_common_check_signal(std_ev
->ev
);
495 if (selrtn
== -1 && errno
== EBADF
) {
496 /* the socket is dead! this should never
497 happen as the socket should have first been
498 made readable and that should have removed
499 the event, so this must be a bug. This is a
501 tevent_debug(std_ev
->ev
, TEVENT_DEBUG_FATAL
,
502 "ERROR: EBADF on std_event_loop_once\n");
503 std_ev
->exit_code
= EBADF
;
507 if (selrtn
== 0 && tvalp
) {
508 /* we don't care about a possible delay here */
509 tevent_common_loop_timer_delay(std_ev
->ev
);
514 /* at least one file descriptor is ready - check
515 which ones and call the handler, being careful to allow
516 the handler to remove itself when called */
517 for (fde
= std_ev
->ev
->fd_events
; fde
; fde
= fde
->next
) {
520 if (FD_ISSET(fde
->fd
, &r_fds
)) flags
|= TEVENT_FD_READ
;
521 if (FD_ISSET(fde
->fd
, &w_fds
)) flags
|= TEVENT_FD_WRITE
;
523 fde
->handler(std_ev
->ev
, fde
, flags
, fde
->private_data
);
524 if (destruction_count
!= std_ev
->destruction_count
) {
535 do a single event loop using the events defined in ev
537 static int std_event_loop_once(struct tevent_context
*ev
)
539 struct std_event_context
*std_ev
= talloc_get_type(ev
->additional_data
,
540 struct std_event_context
);
543 tval
= tevent_common_loop_timer_delay(ev
);
544 if (tevent_timeval_is_zero(&tval
)) {
548 epoll_check_reopen(std_ev
);
550 if (epoll_event_loop(std_ev
, &tval
) == 0) {
554 return std_event_loop_select(std_ev
, &tval
);
558 return on failure or (with 0) if all fd events are removed
560 static int std_event_loop_wait(struct tevent_context
*ev
)
562 struct std_event_context
*std_ev
= talloc_get_type(ev
->additional_data
,
563 struct std_event_context
);
564 std_ev
->exit_code
= 0;
566 while (ev
->fd_events
&& std_ev
->exit_code
== 0) {
567 if (std_event_loop_once(ev
) != 0) {
572 return std_ev
->exit_code
;
575 static const struct tevent_ops std_event_ops
= {
576 .context_init
= std_event_context_init
,
577 .add_fd
= std_event_add_fd
,
578 .set_fd_close_fn
= tevent_common_fd_set_close_fn
,
579 .get_fd_flags
= tevent_common_fd_get_flags
,
580 .set_fd_flags
= std_event_set_fd_flags
,
581 .add_timer
= tevent_common_add_timer
,
582 .add_signal
= tevent_common_add_signal
,
583 .loop_once
= std_event_loop_once
,
584 .loop_wait
= std_event_loop_wait
,
588 bool tevent_standard_init(void)
590 return tevent_register_backend("standard", &std_event_ops
);