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 static void tevent_abort(struct tevent_context *ev, const char *reason);
72 struct tevent_ops_list {
73 struct tevent_ops_list *next, *prev;
75 const struct tevent_ops *ops;
78 /* list of registered event backends */
79 static struct tevent_ops_list *tevent_backends = NULL;
80 static char *tevent_default_backend = NULL;
83 register an events backend
85 bool tevent_register_backend(const char *name, const struct tevent_ops *ops)
87 struct tevent_ops_list *e;
89 for (e = tevent_backends; e != NULL; e = e->next) {
90 if (0 == strcmp(e->name, name)) {
91 /* already registered, skip it */
96 e = talloc(NULL, struct tevent_ops_list);
97 if (e == NULL) return false;
101 DLIST_ADD(tevent_backends, e);
107 set the default event backend
109 void tevent_set_default_backend(const char *backend)
111 talloc_free(tevent_default_backend);
112 tevent_default_backend = talloc_strdup(NULL, backend);
116 initialise backends if not already done
118 static void tevent_backend_init(void)
128 tevent_select_init();
130 tevent_poll_mt_init();
131 #if defined(HAVE_EPOLL)
133 #elif defined(HAVE_SOLARIS_PORTS)
137 tevent_standard_init();
140 _PRIVATE_ const struct tevent_ops *tevent_find_ops_byname(const char *name)
142 struct tevent_ops_list *e;
144 tevent_backend_init();
147 name = tevent_default_backend;
153 for (e = tevent_backends; e != NULL; e = e->next) {
154 if (0 == strcmp(e->name, name)) {
163 list available backends
165 const char **tevent_backend_list(TALLOC_CTX *mem_ctx)
167 const char **list = NULL;
168 struct tevent_ops_list *e;
170 tevent_backend_init();
172 for (e=tevent_backends;e;e=e->next) {
173 list = ev_str_list_add(list, e->name);
176 talloc_steal(mem_ctx, list);
181 static void tevent_common_wakeup_fini(struct tevent_context *ev);
185 static pthread_mutex_t tevent_contexts_mutex = PTHREAD_MUTEX_INITIALIZER;
186 static struct tevent_context *tevent_contexts = NULL;
187 static pthread_once_t tevent_atfork_initialized = PTHREAD_ONCE_INIT;
189 static void tevent_atfork_prepare(void)
191 struct tevent_context *ev;
194 ret = pthread_mutex_lock(&tevent_contexts_mutex);
199 for (ev = tevent_contexts; ev != NULL; ev = ev->next) {
200 ret = pthread_mutex_lock(&ev->scheduled_mutex);
202 tevent_abort(ev, "pthread_mutex_lock failed");
207 static void tevent_atfork_parent(void)
209 struct tevent_context *ev;
212 for (ev = DLIST_TAIL(tevent_contexts); ev != NULL;
213 ev = DLIST_PREV(ev)) {
214 ret = pthread_mutex_unlock(&ev->scheduled_mutex);
216 tevent_abort(ev, "pthread_mutex_unlock failed");
220 ret = pthread_mutex_unlock(&tevent_contexts_mutex);
226 static void tevent_atfork_child(void)
228 struct tevent_context *ev;
231 for (ev = DLIST_TAIL(tevent_contexts); ev != NULL;
232 ev = DLIST_PREV(ev)) {
233 struct tevent_threaded_context *tctx;
235 for (tctx = ev->threaded_contexts; tctx != NULL;
237 tctx->event_ctx = NULL;
240 ev->threaded_contexts = NULL;
242 ret = pthread_mutex_unlock(&ev->scheduled_mutex);
244 tevent_abort(ev, "pthread_mutex_unlock failed");
248 ret = pthread_mutex_unlock(&tevent_contexts_mutex);
254 static void tevent_prep_atfork(void)
258 ret = pthread_atfork(tevent_atfork_prepare,
259 tevent_atfork_parent,
260 tevent_atfork_child);
268 int tevent_common_context_destructor(struct tevent_context *ev)
270 struct tevent_fd *fd, *fn;
271 struct tevent_timer *te, *tn;
272 struct tevent_immediate *ie, *in;
273 struct tevent_signal *se, *sn;
278 ret = pthread_mutex_lock(&tevent_contexts_mutex);
283 DLIST_REMOVE(tevent_contexts, ev);
285 ret = pthread_mutex_unlock(&tevent_contexts_mutex);
291 if (ev->threaded_contexts != NULL) {
293 * Threaded contexts are indicators that threads are
294 * about to send us immediates via
295 * tevent_threaded_schedule_immediate. The caller
296 * needs to make sure that the tevent context lives
297 * long enough to receive immediates from all threads.
299 tevent_abort(ev, "threaded contexts exist");
302 tevent_common_wakeup_fini(ev);
304 for (fd = ev->fd_events; fd; fd = fn) {
306 fd->event_ctx = NULL;
307 DLIST_REMOVE(ev->fd_events, fd);
310 ev->last_zero_timer = NULL;
311 for (te = ev->timer_events; te; te = tn) {
313 te->event_ctx = NULL;
314 DLIST_REMOVE(ev->timer_events, te);
317 for (ie = ev->immediate_events; ie; ie = in) {
319 ie->event_ctx = NULL;
320 ie->cancel_fn = NULL;
321 DLIST_REMOVE(ev->immediate_events, ie);
324 for (se = ev->signal_events; se; se = sn) {
326 se->event_ctx = NULL;
327 DLIST_REMOVE(ev->signal_events, se);
329 * This is important, Otherwise signals
330 * are handled twice in child. eg, SIGHUP.
331 * one added in parent, and another one in
332 * the child. -- BoYang
334 tevent_cleanup_pending_signal_handlers(se);
337 /* removing nesting hook or we get an abort when nesting is
338 * not allowed. -- SSS
339 * Note that we need to leave the allowed flag at its current
340 * value, otherwise the use in tevent_re_initialise() will
341 * leave the event context with allowed forced to false, which
342 * will break users that expect nesting to be allowed
344 ev->nesting.level = 0;
345 ev->nesting.hook_fn = NULL;
346 ev->nesting.hook_private = NULL;
352 create a event_context structure for a specific implemementation.
353 This must be the first events call, and all subsequent calls pass
354 this event_context as the first element. Event handlers also
355 receive this as their first argument.
357 This function is for allowing third-party-applications to hook in gluecode
358 to their own event loop code, so that they can make async usage of our client libs
360 NOTE: use tevent_context_init() inside of samba!
362 struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx,
363 const struct tevent_ops *ops,
364 void *additional_data)
366 struct tevent_context *ev;
369 ev = talloc_zero(mem_ctx, struct tevent_context);
370 if (!ev) return NULL;
374 ret = pthread_once(&tevent_atfork_initialized, tevent_prep_atfork);
380 ret = pthread_mutex_init(&ev->scheduled_mutex, NULL);
386 ret = pthread_mutex_lock(&tevent_contexts_mutex);
388 pthread_mutex_destroy(&ev->scheduled_mutex);
393 DLIST_ADD(tevent_contexts, ev);
395 ret = pthread_mutex_unlock(&tevent_contexts_mutex);
402 talloc_set_destructor(ev, tevent_common_context_destructor);
405 ev->additional_data = additional_data;
407 ret = ev->ops->context_init(ev);
417 create a event_context structure. This must be the first events
418 call, and all subsequent calls pass this event_context as the first
419 element. Event handlers also receive this as their first argument.
421 struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx,
424 const struct tevent_ops *ops;
426 ops = tevent_find_ops_byname(name);
431 return tevent_context_init_ops(mem_ctx, ops, NULL);
436 create a event_context structure. This must be the first events
437 call, and all subsequent calls pass this event_context as the first
438 element. Event handlers also receive this as their first argument.
440 struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx)
442 return tevent_context_init_byname(mem_ctx, NULL);
447 return NULL on failure (memory allocation error)
449 struct tevent_fd *_tevent_add_fd(struct tevent_context *ev,
453 tevent_fd_handler_t handler,
455 const char *handler_name,
456 const char *location)
458 return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data,
459 handler_name, location);
463 set a close function on the fd event
465 void tevent_fd_set_close_fn(struct tevent_fd *fde,
466 tevent_fd_close_fn_t close_fn)
469 if (!fde->event_ctx) return;
470 fde->event_ctx->ops->set_fd_close_fn(fde, close_fn);
473 static void tevent_fd_auto_close_fn(struct tevent_context *ev,
474 struct tevent_fd *fde,
481 void tevent_fd_set_auto_close(struct tevent_fd *fde)
483 tevent_fd_set_close_fn(fde, tevent_fd_auto_close_fn);
487 return the fd event flags
489 uint16_t tevent_fd_get_flags(struct tevent_fd *fde)
492 if (!fde->event_ctx) return 0;
493 return fde->event_ctx->ops->get_fd_flags(fde);
497 set the fd event flags
499 void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags)
502 if (!fde->event_ctx) return;
503 fde->event_ctx->ops->set_fd_flags(fde, flags);
506 bool tevent_signal_support(struct tevent_context *ev)
508 if (ev->ops->add_signal) {
514 static void (*tevent_abort_fn)(const char *reason);
516 void tevent_set_abort_fn(void (*abort_fn)(const char *reason))
518 tevent_abort_fn = abort_fn;
521 static void tevent_abort(struct tevent_context *ev, const char *reason)
523 tevent_debug(ev, TEVENT_DEBUG_FATAL,
524 "abort: %s\n", reason);
526 if (!tevent_abort_fn) {
530 tevent_abort_fn(reason);
535 return NULL on failure
537 struct tevent_timer *_tevent_add_timer(struct tevent_context *ev,
539 struct timeval next_event,
540 tevent_timer_handler_t handler,
542 const char *handler_name,
543 const char *location)
545 return ev->ops->add_timer(ev, mem_ctx, next_event, handler, private_data,
546 handler_name, location);
550 allocate an immediate event
551 return NULL on failure (memory allocation error)
553 struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx,
554 const char *location)
556 struct tevent_immediate *im;
558 im = talloc(mem_ctx, struct tevent_immediate);
559 if (im == NULL) return NULL;
563 im->event_ctx = NULL;
564 im->create_location = location;
566 im->private_data = NULL;
567 im->handler_name = NULL;
568 im->schedule_location = NULL;
569 im->cancel_fn = NULL;
570 im->additional_data = NULL;
576 schedule an immediate event
578 void _tevent_schedule_immediate(struct tevent_immediate *im,
579 struct tevent_context *ev,
580 tevent_immediate_handler_t handler,
582 const char *handler_name,
583 const char *location)
585 ev->ops->schedule_immediate(im, ev, handler, private_data,
586 handler_name, location);
592 sa_flags are flags to sigaction(2)
594 return NULL on failure
596 struct tevent_signal *_tevent_add_signal(struct tevent_context *ev,
600 tevent_signal_handler_t handler,
602 const char *handler_name,
603 const char *location)
605 return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data,
606 handler_name, location);
609 void tevent_loop_allow_nesting(struct tevent_context *ev)
611 ev->nesting.allowed = true;
614 void tevent_loop_set_nesting_hook(struct tevent_context *ev,
615 tevent_nesting_hook hook,
618 if (ev->nesting.hook_fn &&
619 (ev->nesting.hook_fn != hook ||
620 ev->nesting.hook_private != private_data)) {
621 /* the way the nesting hook code is currently written
622 we cannot support two different nesting hooks at the
624 tevent_abort(ev, "tevent: Violation of nesting hook rules\n");
626 ev->nesting.hook_fn = hook;
627 ev->nesting.hook_private = private_data;
630 static void tevent_abort_nesting(struct tevent_context *ev, const char *location)
634 reason = talloc_asprintf(NULL, "tevent_loop_once() nesting at %s",
637 reason = "tevent_loop_once() nesting";
640 tevent_abort(ev, reason);
644 do a single event loop using the events defined in ev
646 int _tevent_loop_once(struct tevent_context *ev, const char *location)
649 void *nesting_stack_ptr = NULL;
653 if (ev->nesting.level > 1) {
654 if (!ev->nesting.allowed) {
655 tevent_abort_nesting(ev, location);
660 if (ev->nesting.level > 0) {
661 if (ev->nesting.hook_fn) {
663 ret2 = ev->nesting.hook_fn(ev,
664 ev->nesting.hook_private,
667 (void *)&nesting_stack_ptr,
676 tevent_trace_point_callback(ev, TEVENT_TRACE_BEFORE_LOOP_ONCE);
677 ret = ev->ops->loop_once(ev, location);
678 tevent_trace_point_callback(ev, TEVENT_TRACE_AFTER_LOOP_ONCE);
680 if (ev->nesting.level > 0) {
681 if (ev->nesting.hook_fn) {
683 ret2 = ev->nesting.hook_fn(ev,
684 ev->nesting.hook_private,
687 (void *)&nesting_stack_ptr,
702 this is a performance optimization for the samba4 nested event loop problems
704 int _tevent_loop_until(struct tevent_context *ev,
705 bool (*finished)(void *private_data),
707 const char *location)
710 void *nesting_stack_ptr = NULL;
714 if (ev->nesting.level > 1) {
715 if (!ev->nesting.allowed) {
716 tevent_abort_nesting(ev, location);
721 if (ev->nesting.level > 0) {
722 if (ev->nesting.hook_fn) {
724 ret2 = ev->nesting.hook_fn(ev,
725 ev->nesting.hook_private,
728 (void *)&nesting_stack_ptr,
737 while (!finished(private_data)) {
738 tevent_trace_point_callback(ev, TEVENT_TRACE_BEFORE_LOOP_ONCE);
739 ret = ev->ops->loop_once(ev, location);
740 tevent_trace_point_callback(ev, TEVENT_TRACE_AFTER_LOOP_ONCE);
746 if (ev->nesting.level > 0) {
747 if (ev->nesting.hook_fn) {
749 ret2 = ev->nesting.hook_fn(ev,
750 ev->nesting.hook_private,
753 (void *)&nesting_stack_ptr,
767 bool tevent_common_have_events(struct tevent_context *ev)
769 if (ev->fd_events != NULL) {
770 if (ev->fd_events != ev->pipe_fde) {
773 if (ev->fd_events->next != NULL) {
778 * At this point we just have the wakeup pipe event as
779 * the only fd_event. That one does not count as a
780 * regular event, so look at the other event types.
784 return ((ev->timer_events != NULL) ||
785 (ev->immediate_events != NULL) ||
786 (ev->signal_events != NULL));
790 return on failure or (with 0) if all fd events are removed
792 int tevent_common_loop_wait(struct tevent_context *ev,
793 const char *location)
796 * loop as long as we have events pending
798 while (tevent_common_have_events(ev)) {
800 ret = _tevent_loop_once(ev, location);
802 tevent_debug(ev, TEVENT_DEBUG_FATAL,
803 "_tevent_loop_once() failed: %d - %s\n",
804 ret, strerror(errno));
809 tevent_debug(ev, TEVENT_DEBUG_WARNING,
810 "tevent_common_loop_wait() out of events\n");
815 return on failure or (with 0) if all fd events are removed
817 int _tevent_loop_wait(struct tevent_context *ev, const char *location)
819 return ev->ops->loop_wait(ev, location);
824 re-initialise a tevent context. This leaves you with the same
825 event context, but all events are wiped and the structure is
826 re-initialised. This is most useful after a fork()
828 zero is returned on success, non-zero on failure
830 int tevent_re_initialise(struct tevent_context *ev)
832 tevent_common_context_destructor(ev);
834 return ev->ops->context_init(ev);
837 static void wakeup_pipe_handler(struct tevent_context *ev,
838 struct tevent_fd *fde,
839 uint16_t flags, void *_private)
843 /* its non-blocking, doesn't matter if we read too much */
846 ret = read(fde->fd, c, sizeof(c));
847 } while (ret == -1 && errno == EINTR);
851 * Initialize the wakeup pipe and pipe fde
854 int tevent_common_wakeup_init(struct tevent_context *ev)
858 if (ev->pipe_fde != NULL) {
862 ret = pipe(ev->pipe_fds);
866 ev_set_blocking(ev->pipe_fds[0], false);
867 ev_set_blocking(ev->pipe_fds[1], false);
869 ev->pipe_fde = tevent_add_fd(ev, ev, ev->pipe_fds[0],
871 wakeup_pipe_handler, NULL);
872 if (ev->pipe_fde == NULL) {
873 close(ev->pipe_fds[0]);
874 close(ev->pipe_fds[1]);
881 int tevent_common_wakeup(struct tevent_context *ev)
885 if (ev->pipe_fds[1] == -1) {
891 ret = write(ev->pipe_fds[1], &c, 1);
892 } while ((ret == -1) && (errno == EINTR));
897 static void tevent_common_wakeup_fini(struct tevent_context *ev)
899 if (ev->pipe_fde == NULL) {
903 TALLOC_FREE(ev->pipe_fde);
905 close(ev->pipe_fds[0]);
906 close(ev->pipe_fds[1]);