2 Unix SMB/CIFS implementation.
3 main select loop and event handling
4 Copyright (C) Andrew Tridgell 2003
5 Copyright (C) Stefan Metzmacher 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 PLEASE READ THIS BEFORE MODIFYING!
28 This module is a general abstraction for the main select loop and
29 event handling. Do not ever put any localised hacks in here, instead
30 register one of the possible event types and implement that event
33 There are 2 types of event handling that are handled in this module:
35 1) a file descriptor becoming readable or writeable. This is mostly
36 used for network sockets, but can be used for any type of file
37 descriptor. You may only register one handler for each file
38 descriptor/io combination or you will get unpredictable results
39 (this means that you can have a handler for read events, and a
40 separate handler for write events, but not two handlers that are
41 both handling read events)
43 2) a timed event. You can register an event that happens at a
44 specific time. You can register as many of these as you
45 like. They are single shot - add a new timed event in the event
46 handler to get another event.
48 To setup a set of events you first need to create a event_context
49 structure using the function tevent_context_init(); This returns a
50 'struct tevent_context' that you use in all subsequent calls.
52 After that you can add/remove events that you are interested in
53 using tevent_add_*() and talloc_free()
55 Finally, you call tevent_loop_wait_once() to block waiting for one of the
56 events to occor or tevent_loop_wait() which will loop
61 #include "system/filesys.h"
63 #include "system/threads.h"
65 #define TEVENT_DEPRECATED 1
67 #include "tevent_internal.h"
68 #include "tevent_util.h"
70 #include <sys/eventfd.h>
73 static void tevent_abort(struct tevent_context
*ev
, const char *reason
);
75 struct tevent_ops_list
{
76 struct tevent_ops_list
*next
, *prev
;
78 const struct tevent_ops
*ops
;
81 /* list of registered event backends */
82 static struct tevent_ops_list
*tevent_backends
= NULL
;
83 static char *tevent_default_backend
= NULL
;
86 register an events backend
88 bool tevent_register_backend(const char *name
, const struct tevent_ops
*ops
)
90 struct tevent_ops_list
*e
;
92 for (e
= tevent_backends
; e
!= NULL
; e
= e
->next
) {
93 if (0 == strcmp(e
->name
, name
)) {
94 /* already registered, skip it */
99 e
= talloc(NULL
, struct tevent_ops_list
);
100 if (e
== NULL
) return false;
104 DLIST_ADD(tevent_backends
, e
);
110 set the default event backend
112 void tevent_set_default_backend(const char *backend
)
114 talloc_free(tevent_default_backend
);
115 tevent_default_backend
= talloc_strdup(NULL
, backend
);
119 initialise backends if not already done
121 static void tevent_backend_init(void)
131 tevent_select_init();
133 tevent_poll_mt_init();
134 #if defined(HAVE_EPOLL)
136 #elif defined(HAVE_SOLARIS_PORTS)
140 tevent_standard_init();
143 _PRIVATE_
const struct tevent_ops
*tevent_find_ops_byname(const char *name
)
145 struct tevent_ops_list
*e
;
147 tevent_backend_init();
150 name
= tevent_default_backend
;
156 for (e
= tevent_backends
; e
!= NULL
; e
= e
->next
) {
157 if (0 == strcmp(e
->name
, name
)) {
166 list available backends
168 const char **tevent_backend_list(TALLOC_CTX
*mem_ctx
)
170 const char **list
= NULL
;
171 struct tevent_ops_list
*e
;
173 tevent_backend_init();
175 for (e
=tevent_backends
;e
;e
=e
->next
) {
176 list
= ev_str_list_add(list
, e
->name
);
179 talloc_steal(mem_ctx
, list
);
184 static void tevent_common_wakeup_fini(struct tevent_context
*ev
);
188 static pthread_mutex_t tevent_contexts_mutex
= PTHREAD_MUTEX_INITIALIZER
;
189 static struct tevent_context
*tevent_contexts
= NULL
;
190 static pthread_once_t tevent_atfork_initialized
= PTHREAD_ONCE_INIT
;
192 static void tevent_atfork_prepare(void)
194 struct tevent_context
*ev
;
197 ret
= pthread_mutex_lock(&tevent_contexts_mutex
);
202 for (ev
= tevent_contexts
; ev
!= NULL
; ev
= ev
->next
) {
203 struct tevent_threaded_context
*tctx
;
205 for (tctx
= ev
->threaded_contexts
; tctx
!= NULL
;
207 ret
= pthread_mutex_lock(&tctx
->event_ctx_mutex
);
209 tevent_abort(ev
, "pthread_mutex_lock failed");
213 ret
= pthread_mutex_lock(&ev
->scheduled_mutex
);
215 tevent_abort(ev
, "pthread_mutex_lock failed");
220 static void tevent_atfork_parent(void)
222 struct tevent_context
*ev
;
225 for (ev
= DLIST_TAIL(tevent_contexts
); ev
!= NULL
;
226 ev
= DLIST_PREV(ev
)) {
227 struct tevent_threaded_context
*tctx
;
229 ret
= pthread_mutex_unlock(&ev
->scheduled_mutex
);
231 tevent_abort(ev
, "pthread_mutex_unlock failed");
234 for (tctx
= DLIST_TAIL(ev
->threaded_contexts
); tctx
!= NULL
;
235 tctx
= DLIST_PREV(tctx
)) {
236 ret
= pthread_mutex_unlock(&tctx
->event_ctx_mutex
);
239 ev
, "pthread_mutex_unlock failed");
244 ret
= pthread_mutex_unlock(&tevent_contexts_mutex
);
250 static void tevent_atfork_child(void)
252 struct tevent_context
*ev
;
255 for (ev
= DLIST_TAIL(tevent_contexts
); ev
!= NULL
;
256 ev
= DLIST_PREV(ev
)) {
257 struct tevent_threaded_context
*tctx
;
259 for (tctx
= DLIST_TAIL(ev
->threaded_contexts
); tctx
!= NULL
;
260 tctx
= DLIST_PREV(tctx
)) {
261 tctx
->event_ctx
= NULL
;
263 ret
= pthread_mutex_unlock(&tctx
->event_ctx_mutex
);
266 ev
, "pthread_mutex_unlock failed");
270 ev
->threaded_contexts
= NULL
;
272 ret
= pthread_mutex_unlock(&ev
->scheduled_mutex
);
274 tevent_abort(ev
, "pthread_mutex_unlock failed");
278 ret
= pthread_mutex_unlock(&tevent_contexts_mutex
);
284 static void tevent_prep_atfork(void)
288 ret
= pthread_atfork(tevent_atfork_prepare
,
289 tevent_atfork_parent
,
290 tevent_atfork_child
);
298 int tevent_common_context_destructor(struct tevent_context
*ev
)
300 struct tevent_fd
*fd
, *fn
;
301 struct tevent_timer
*te
, *tn
;
302 struct tevent_immediate
*ie
, *in
;
303 struct tevent_signal
*se
, *sn
;
308 ret
= pthread_mutex_lock(&tevent_contexts_mutex
);
313 DLIST_REMOVE(tevent_contexts
, ev
);
315 ret
= pthread_mutex_unlock(&tevent_contexts_mutex
);
320 while (ev
->threaded_contexts
!= NULL
) {
321 struct tevent_threaded_context
*tctx
= ev
->threaded_contexts
;
323 ret
= pthread_mutex_lock(&tctx
->event_ctx_mutex
);
329 * Indicate to the thread that the tevent_context is
330 * gone. The counterpart of this is in
331 * _tevent_threaded_schedule_immediate, there we read
332 * this under the threaded_context's mutex.
335 tctx
->event_ctx
= NULL
;
337 ret
= pthread_mutex_unlock(&tctx
->event_ctx_mutex
);
342 DLIST_REMOVE(ev
->threaded_contexts
, tctx
);
346 tevent_common_wakeup_fini(ev
);
348 for (fd
= ev
->fd_events
; fd
; fd
= fn
) {
350 fd
->event_ctx
= NULL
;
351 DLIST_REMOVE(ev
->fd_events
, fd
);
354 ev
->last_zero_timer
= NULL
;
355 for (te
= ev
->timer_events
; te
; te
= tn
) {
357 te
->event_ctx
= NULL
;
358 DLIST_REMOVE(ev
->timer_events
, te
);
361 for (ie
= ev
->immediate_events
; ie
; ie
= in
) {
363 ie
->event_ctx
= NULL
;
364 ie
->cancel_fn
= NULL
;
365 DLIST_REMOVE(ev
->immediate_events
, ie
);
368 for (se
= ev
->signal_events
; se
; se
= sn
) {
370 se
->event_ctx
= NULL
;
371 DLIST_REMOVE(ev
->signal_events
, se
);
373 * This is important, Otherwise signals
374 * are handled twice in child. eg, SIGHUP.
375 * one added in parent, and another one in
376 * the child. -- BoYang
378 tevent_cleanup_pending_signal_handlers(se
);
381 /* removing nesting hook or we get an abort when nesting is
382 * not allowed. -- SSS
383 * Note that we need to leave the allowed flag at its current
384 * value, otherwise the use in tevent_re_initialise() will
385 * leave the event context with allowed forced to false, which
386 * will break users that expect nesting to be allowed
388 ev
->nesting
.level
= 0;
389 ev
->nesting
.hook_fn
= NULL
;
390 ev
->nesting
.hook_private
= NULL
;
396 create a event_context structure for a specific implemementation.
397 This must be the first events call, and all subsequent calls pass
398 this event_context as the first element. Event handlers also
399 receive this as their first argument.
401 This function is for allowing third-party-applications to hook in gluecode
402 to their own event loop code, so that they can make async usage of our client libs
404 NOTE: use tevent_context_init() inside of samba!
406 struct tevent_context
*tevent_context_init_ops(TALLOC_CTX
*mem_ctx
,
407 const struct tevent_ops
*ops
,
408 void *additional_data
)
410 struct tevent_context
*ev
;
413 ev
= talloc_zero(mem_ctx
, struct tevent_context
);
414 if (!ev
) return NULL
;
418 ret
= pthread_once(&tevent_atfork_initialized
, tevent_prep_atfork
);
424 ret
= pthread_mutex_init(&ev
->scheduled_mutex
, NULL
);
430 ret
= pthread_mutex_lock(&tevent_contexts_mutex
);
432 pthread_mutex_destroy(&ev
->scheduled_mutex
);
437 DLIST_ADD(tevent_contexts
, ev
);
439 ret
= pthread_mutex_unlock(&tevent_contexts_mutex
);
446 talloc_set_destructor(ev
, tevent_common_context_destructor
);
449 ev
->additional_data
= additional_data
;
451 ret
= ev
->ops
->context_init(ev
);
461 create a event_context structure. This must be the first events
462 call, and all subsequent calls pass this event_context as the first
463 element. Event handlers also receive this as their first argument.
465 struct tevent_context
*tevent_context_init_byname(TALLOC_CTX
*mem_ctx
,
468 const struct tevent_ops
*ops
;
470 ops
= tevent_find_ops_byname(name
);
475 return tevent_context_init_ops(mem_ctx
, ops
, NULL
);
480 create a event_context structure. This must be the first events
481 call, and all subsequent calls pass this event_context as the first
482 element. Event handlers also receive this as their first argument.
484 struct tevent_context
*tevent_context_init(TALLOC_CTX
*mem_ctx
)
486 return tevent_context_init_byname(mem_ctx
, NULL
);
491 return NULL on failure (memory allocation error)
493 struct tevent_fd
*_tevent_add_fd(struct tevent_context
*ev
,
497 tevent_fd_handler_t handler
,
499 const char *handler_name
,
500 const char *location
)
502 return ev
->ops
->add_fd(ev
, mem_ctx
, fd
, flags
, handler
, private_data
,
503 handler_name
, location
);
507 set a close function on the fd event
509 void tevent_fd_set_close_fn(struct tevent_fd
*fde
,
510 tevent_fd_close_fn_t close_fn
)
513 if (!fde
->event_ctx
) return;
514 fde
->event_ctx
->ops
->set_fd_close_fn(fde
, close_fn
);
517 static void tevent_fd_auto_close_fn(struct tevent_context
*ev
,
518 struct tevent_fd
*fde
,
525 void tevent_fd_set_auto_close(struct tevent_fd
*fde
)
527 tevent_fd_set_close_fn(fde
, tevent_fd_auto_close_fn
);
531 return the fd event flags
533 uint16_t tevent_fd_get_flags(struct tevent_fd
*fde
)
536 if (!fde
->event_ctx
) return 0;
537 return fde
->event_ctx
->ops
->get_fd_flags(fde
);
541 set the fd event flags
543 void tevent_fd_set_flags(struct tevent_fd
*fde
, uint16_t flags
)
546 if (!fde
->event_ctx
) return;
547 fde
->event_ctx
->ops
->set_fd_flags(fde
, flags
);
550 bool tevent_signal_support(struct tevent_context
*ev
)
552 if (ev
->ops
->add_signal
) {
558 static void (*tevent_abort_fn
)(const char *reason
);
560 void tevent_set_abort_fn(void (*abort_fn
)(const char *reason
))
562 tevent_abort_fn
= abort_fn
;
565 static void tevent_abort(struct tevent_context
*ev
, const char *reason
)
567 tevent_debug(ev
, TEVENT_DEBUG_FATAL
,
568 "abort: %s\n", reason
);
570 if (!tevent_abort_fn
) {
574 tevent_abort_fn(reason
);
579 return NULL on failure
581 struct tevent_timer
*_tevent_add_timer(struct tevent_context
*ev
,
583 struct timeval next_event
,
584 tevent_timer_handler_t handler
,
586 const char *handler_name
,
587 const char *location
)
589 return ev
->ops
->add_timer(ev
, mem_ctx
, next_event
, handler
, private_data
,
590 handler_name
, location
);
594 allocate an immediate event
595 return NULL on failure (memory allocation error)
597 struct tevent_immediate
*_tevent_create_immediate(TALLOC_CTX
*mem_ctx
,
598 const char *location
)
600 struct tevent_immediate
*im
;
602 im
= talloc(mem_ctx
, struct tevent_immediate
);
603 if (im
== NULL
) return NULL
;
607 im
->event_ctx
= NULL
;
608 im
->create_location
= location
;
610 im
->private_data
= NULL
;
611 im
->handler_name
= NULL
;
612 im
->schedule_location
= NULL
;
613 im
->cancel_fn
= NULL
;
614 im
->additional_data
= NULL
;
620 schedule an immediate event
622 void _tevent_schedule_immediate(struct tevent_immediate
*im
,
623 struct tevent_context
*ev
,
624 tevent_immediate_handler_t handler
,
626 const char *handler_name
,
627 const char *location
)
629 ev
->ops
->schedule_immediate(im
, ev
, handler
, private_data
,
630 handler_name
, location
);
636 sa_flags are flags to sigaction(2)
638 return NULL on failure
640 struct tevent_signal
*_tevent_add_signal(struct tevent_context
*ev
,
644 tevent_signal_handler_t handler
,
646 const char *handler_name
,
647 const char *location
)
649 return ev
->ops
->add_signal(ev
, mem_ctx
, signum
, sa_flags
, handler
, private_data
,
650 handler_name
, location
);
653 void tevent_loop_allow_nesting(struct tevent_context
*ev
)
655 ev
->nesting
.allowed
= true;
658 void tevent_loop_set_nesting_hook(struct tevent_context
*ev
,
659 tevent_nesting_hook hook
,
662 if (ev
->nesting
.hook_fn
&&
663 (ev
->nesting
.hook_fn
!= hook
||
664 ev
->nesting
.hook_private
!= private_data
)) {
665 /* the way the nesting hook code is currently written
666 we cannot support two different nesting hooks at the
668 tevent_abort(ev
, "tevent: Violation of nesting hook rules\n");
670 ev
->nesting
.hook_fn
= hook
;
671 ev
->nesting
.hook_private
= private_data
;
674 static void tevent_abort_nesting(struct tevent_context
*ev
, const char *location
)
678 reason
= talloc_asprintf(NULL
, "tevent_loop_once() nesting at %s",
681 reason
= "tevent_loop_once() nesting";
684 tevent_abort(ev
, reason
);
688 do a single event loop using the events defined in ev
690 int _tevent_loop_once(struct tevent_context
*ev
, const char *location
)
693 void *nesting_stack_ptr
= NULL
;
697 if (ev
->nesting
.level
> 1) {
698 if (!ev
->nesting
.allowed
) {
699 tevent_abort_nesting(ev
, location
);
704 if (ev
->nesting
.level
> 0) {
705 if (ev
->nesting
.hook_fn
) {
707 ret2
= ev
->nesting
.hook_fn(ev
,
708 ev
->nesting
.hook_private
,
711 (void *)&nesting_stack_ptr
,
720 tevent_trace_point_callback(ev
, TEVENT_TRACE_BEFORE_LOOP_ONCE
);
721 ret
= ev
->ops
->loop_once(ev
, location
);
722 tevent_trace_point_callback(ev
, TEVENT_TRACE_AFTER_LOOP_ONCE
);
724 if (ev
->nesting
.level
> 0) {
725 if (ev
->nesting
.hook_fn
) {
727 ret2
= ev
->nesting
.hook_fn(ev
,
728 ev
->nesting
.hook_private
,
731 (void *)&nesting_stack_ptr
,
746 this is a performance optimization for the samba4 nested event loop problems
748 int _tevent_loop_until(struct tevent_context
*ev
,
749 bool (*finished
)(void *private_data
),
751 const char *location
)
754 void *nesting_stack_ptr
= NULL
;
758 if (ev
->nesting
.level
> 1) {
759 if (!ev
->nesting
.allowed
) {
760 tevent_abort_nesting(ev
, location
);
765 if (ev
->nesting
.level
> 0) {
766 if (ev
->nesting
.hook_fn
) {
768 ret2
= ev
->nesting
.hook_fn(ev
,
769 ev
->nesting
.hook_private
,
772 (void *)&nesting_stack_ptr
,
781 while (!finished(private_data
)) {
782 tevent_trace_point_callback(ev
, TEVENT_TRACE_BEFORE_LOOP_ONCE
);
783 ret
= ev
->ops
->loop_once(ev
, location
);
784 tevent_trace_point_callback(ev
, TEVENT_TRACE_AFTER_LOOP_ONCE
);
790 if (ev
->nesting
.level
> 0) {
791 if (ev
->nesting
.hook_fn
) {
793 ret2
= ev
->nesting
.hook_fn(ev
,
794 ev
->nesting
.hook_private
,
797 (void *)&nesting_stack_ptr
,
811 bool tevent_common_have_events(struct tevent_context
*ev
)
813 if (ev
->fd_events
!= NULL
) {
814 if (ev
->fd_events
!= ev
->wakeup_fde
) {
817 if (ev
->fd_events
->next
!= NULL
) {
822 * At this point we just have the wakeup pipe event as
823 * the only fd_event. That one does not count as a
824 * regular event, so look at the other event types.
828 return ((ev
->timer_events
!= NULL
) ||
829 (ev
->immediate_events
!= NULL
) ||
830 (ev
->signal_events
!= NULL
));
834 return on failure or (with 0) if all fd events are removed
836 int tevent_common_loop_wait(struct tevent_context
*ev
,
837 const char *location
)
840 * loop as long as we have events pending
842 while (tevent_common_have_events(ev
)) {
844 ret
= _tevent_loop_once(ev
, location
);
846 tevent_debug(ev
, TEVENT_DEBUG_FATAL
,
847 "_tevent_loop_once() failed: %d - %s\n",
848 ret
, strerror(errno
));
853 tevent_debug(ev
, TEVENT_DEBUG_WARNING
,
854 "tevent_common_loop_wait() out of events\n");
859 return on failure or (with 0) if all fd events are removed
861 int _tevent_loop_wait(struct tevent_context
*ev
, const char *location
)
863 return ev
->ops
->loop_wait(ev
, location
);
868 re-initialise a tevent context. This leaves you with the same
869 event context, but all events are wiped and the structure is
870 re-initialised. This is most useful after a fork()
872 zero is returned on success, non-zero on failure
874 int tevent_re_initialise(struct tevent_context
*ev
)
876 tevent_common_context_destructor(ev
);
878 return ev
->ops
->context_init(ev
);
881 static void wakeup_pipe_handler(struct tevent_context
*ev
,
882 struct tevent_fd
*fde
,
883 uint16_t flags
, void *_private
)
889 * This is the boilerplate for eventfd, but it works
890 * for pipes too. And as we don't care about the data
891 * we read, we're fine.
894 ret
= read(fde
->fd
, &val
, sizeof(val
));
895 } while (ret
== -1 && errno
== EINTR
);
899 * Initialize the wakeup pipe and pipe fde
902 int tevent_common_wakeup_init(struct tevent_context
*ev
)
906 if (ev
->wakeup_fde
!= NULL
) {
911 ret
= eventfd(0, EFD_NONBLOCK
);
915 read_fd
= ev
->wakeup_fd
= ret
;
919 ret
= pipe(pipe_fds
);
923 ev
->wakeup_fd
= pipe_fds
[1];
924 ev
->wakeup_read_fd
= pipe_fds
[0];
926 ev_set_blocking(ev
->wakeup_fd
, false);
927 ev_set_blocking(ev
->wakeup_read_fd
, false);
929 read_fd
= ev
->wakeup_read_fd
;
933 ev
->wakeup_fde
= tevent_add_fd(ev
, ev
, read_fd
, TEVENT_FD_READ
,
934 wakeup_pipe_handler
, NULL
);
935 if (ev
->wakeup_fde
== NULL
) {
936 close(ev
->wakeup_fd
);
938 close(ev
->wakeup_read_fd
);
946 int tevent_common_wakeup_fd(int fd
)
953 ret
= write(fd
, &val
, sizeof(val
));
956 ret
= write(fd
, &c
, 1);
958 } while ((ret
== -1) && (errno
== EINTR
));
963 int tevent_common_wakeup(struct tevent_context
*ev
)
965 if (ev
->wakeup_fde
== NULL
) {
969 return tevent_common_wakeup_fd(ev
->wakeup_fd
);
972 static void tevent_common_wakeup_fini(struct tevent_context
*ev
)
974 if (ev
->wakeup_fde
== NULL
) {
978 TALLOC_FREE(ev
->wakeup_fde
);
980 close(ev
->wakeup_fd
);
982 close(ev
->wakeup_read_fd
);