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 struct tevent_ops_list
{
74 struct tevent_ops_list
*next
, *prev
;
76 const struct tevent_ops
*ops
;
79 /* list of registered event backends */
80 static struct tevent_ops_list
*tevent_backends
= NULL
;
81 static char *tevent_default_backend
= NULL
;
84 register an events backend
86 bool tevent_register_backend(const char *name
, const struct tevent_ops
*ops
)
88 struct tevent_ops_list
*e
;
90 for (e
= tevent_backends
; e
!= NULL
; e
= e
->next
) {
91 if (0 == strcmp(e
->name
, name
)) {
92 /* already registered, skip it */
97 e
= talloc(NULL
, struct tevent_ops_list
);
98 if (e
== NULL
) return false;
102 DLIST_ADD(tevent_backends
, e
);
108 set the default event backend
110 void tevent_set_default_backend(const char *backend
)
112 talloc_free(tevent_default_backend
);
113 tevent_default_backend
= talloc_strdup(NULL
, backend
);
117 initialise backends if not already done
119 static void tevent_backend_init(void)
130 tevent_poll_mt_init();
131 #if defined(HAVE_EPOLL)
135 tevent_standard_init();
138 const struct tevent_ops
*tevent_find_ops_byname(const char *name
)
140 struct tevent_ops_list
*e
;
142 tevent_backend_init();
145 name
= tevent_default_backend
;
151 for (e
= tevent_backends
; e
!= NULL
; e
= e
->next
) {
152 if (0 == strcmp(e
->name
, name
)) {
161 list available backends
163 const char **tevent_backend_list(TALLOC_CTX
*mem_ctx
)
165 const char **list
= NULL
;
166 struct tevent_ops_list
*e
;
169 tevent_backend_init();
171 for (e
=tevent_backends
;e
;e
=e
->next
) {
175 list
= talloc_zero_array(mem_ctx
, const char *, idx
+1);
181 for (e
=tevent_backends
;e
;e
=e
->next
) {
182 list
[idx
] = talloc_strdup(list
, e
->name
);
183 if (list
[idx
] == NULL
) {
193 static void tevent_common_wakeup_fini(struct tevent_context
*ev
);
197 static pthread_mutex_t tevent_contexts_mutex
= PTHREAD_MUTEX_INITIALIZER
;
198 static struct tevent_context
*tevent_contexts
= NULL
;
199 static pthread_once_t tevent_atfork_initialized
= PTHREAD_ONCE_INIT
;
200 static pid_t tevent_cached_global_pid
= 0;
202 static void tevent_atfork_prepare(void)
204 struct tevent_context
*ev
;
207 ret
= pthread_mutex_lock(&tevent_contexts_mutex
);
212 for (ev
= tevent_contexts
; ev
!= NULL
; ev
= ev
->next
) {
213 struct tevent_threaded_context
*tctx
;
215 for (tctx
= ev
->threaded_contexts
; tctx
!= NULL
;
217 ret
= pthread_mutex_lock(&tctx
->event_ctx_mutex
);
219 tevent_abort(ev
, "pthread_mutex_lock failed");
223 ret
= pthread_mutex_lock(&ev
->scheduled_mutex
);
225 tevent_abort(ev
, "pthread_mutex_lock failed");
230 static void tevent_atfork_parent(void)
232 struct tevent_context
*ev
;
235 for (ev
= DLIST_TAIL(tevent_contexts
); ev
!= NULL
;
236 ev
= DLIST_PREV(ev
)) {
237 struct tevent_threaded_context
*tctx
;
239 ret
= pthread_mutex_unlock(&ev
->scheduled_mutex
);
241 tevent_abort(ev
, "pthread_mutex_unlock failed");
244 for (tctx
= DLIST_TAIL(ev
->threaded_contexts
); tctx
!= NULL
;
245 tctx
= DLIST_PREV(tctx
)) {
246 ret
= pthread_mutex_unlock(&tctx
->event_ctx_mutex
);
249 ev
, "pthread_mutex_unlock failed");
254 ret
= pthread_mutex_unlock(&tevent_contexts_mutex
);
260 static void tevent_atfork_child(void)
262 struct tevent_context
*ev
;
265 tevent_cached_global_pid
= getpid();
267 for (ev
= DLIST_TAIL(tevent_contexts
); ev
!= NULL
;
268 ev
= DLIST_PREV(ev
)) {
269 struct tevent_threaded_context
*tctx
;
271 for (tctx
= DLIST_TAIL(ev
->threaded_contexts
); tctx
!= NULL
;
272 tctx
= DLIST_PREV(tctx
)) {
273 tctx
->event_ctx
= NULL
;
275 ret
= pthread_mutex_unlock(&tctx
->event_ctx_mutex
);
278 ev
, "pthread_mutex_unlock failed");
282 ev
->threaded_contexts
= NULL
;
284 ret
= pthread_mutex_unlock(&ev
->scheduled_mutex
);
286 tevent_abort(ev
, "pthread_mutex_unlock failed");
290 ret
= pthread_mutex_unlock(&tevent_contexts_mutex
);
296 static void tevent_prep_atfork(void)
300 ret
= pthread_atfork(tevent_atfork_prepare
,
301 tevent_atfork_parent
,
302 tevent_atfork_child
);
307 tevent_cached_global_pid
= getpid();
312 static int tevent_init_globals(void)
317 ret
= pthread_once(&tevent_atfork_initialized
, tevent_prep_atfork
);
326 _PUBLIC_ pid_t
tevent_cached_getpid(void)
329 tevent_init_globals();
330 #ifdef TEVENT_VERIFY_CACHED_GETPID
331 if (tevent_cached_global_pid
!= getpid()) {
332 tevent_abort(NULL
, "tevent_cached_global_pid invalid");
335 if (tevent_cached_global_pid
!= 0) {
336 return tevent_cached_global_pid
;
342 int tevent_common_context_destructor(struct tevent_context
*ev
)
344 struct tevent_fd
*fd
, *fn
;
345 struct tevent_timer
*te
, *tn
;
346 struct tevent_immediate
*ie
, *in
;
347 struct tevent_signal
*se
, *sn
;
348 struct tevent_wrapper_glue
*gl
, *gn
;
353 if (ev
->wrapper
.glue
!= NULL
) {
355 "tevent_common_context_destructor() active on wrapper");
359 ret
= pthread_mutex_lock(&tevent_contexts_mutex
);
364 DLIST_REMOVE(tevent_contexts
, ev
);
366 ret
= pthread_mutex_unlock(&tevent_contexts_mutex
);
371 while (ev
->threaded_contexts
!= NULL
) {
372 struct tevent_threaded_context
*tctx
= ev
->threaded_contexts
;
374 ret
= pthread_mutex_lock(&tctx
->event_ctx_mutex
);
380 * Indicate to the thread that the tevent_context is
381 * gone. The counterpart of this is in
382 * _tevent_threaded_schedule_immediate, there we read
383 * this under the threaded_context's mutex.
386 tctx
->event_ctx
= NULL
;
388 ret
= pthread_mutex_unlock(&tctx
->event_ctx_mutex
);
393 DLIST_REMOVE(ev
->threaded_contexts
, tctx
);
396 ret
= pthread_mutex_destroy(&ev
->scheduled_mutex
);
402 for (gl
= ev
->wrapper
.list
; gl
; gl
= gn
) {
406 DLIST_REMOVE(ev
->wrapper
.list
, gl
);
409 tevent_common_wakeup_fini(ev
);
411 for (fd
= ev
->fd_events
; fd
; fd
= fn
) {
413 tevent_common_fd_disarm(fd
);
416 ev
->last_zero_timer
= NULL
;
417 for (te
= ev
->timer_events
; te
; te
= tn
) {
419 tevent_trace_timer_callback(te
->event_ctx
, te
, TEVENT_EVENT_TRACE_DETACH
);
421 te
->event_ctx
= NULL
;
422 DLIST_REMOVE(ev
->timer_events
, te
);
425 for (ie
= ev
->immediate_events
; ie
; ie
= in
) {
427 tevent_trace_immediate_callback(ie
->event_ctx
, ie
, TEVENT_EVENT_TRACE_DETACH
);
429 ie
->event_ctx
= NULL
;
430 ie
->cancel_fn
= NULL
;
431 DLIST_REMOVE(ev
->immediate_events
, ie
);
434 for (se
= ev
->signal_events
; se
; se
= sn
) {
436 tevent_trace_signal_callback(se
->event_ctx
, se
, TEVENT_EVENT_TRACE_DETACH
);
438 se
->event_ctx
= NULL
;
439 DLIST_REMOVE(ev
->signal_events
, se
);
441 * This is important, Otherwise signals
442 * are handled twice in child. eg, SIGHUP.
443 * one added in parent, and another one in
444 * the child. -- BoYang
446 tevent_cleanup_pending_signal_handlers(se
);
449 /* removing nesting hook or we get an abort when nesting is
450 * not allowed. -- SSS
451 * Note that we need to leave the allowed flag at its current
452 * value, otherwise the use in tevent_re_initialise() will
453 * leave the event context with allowed forced to false, which
454 * will break users that expect nesting to be allowed
456 ev
->nesting
.level
= 0;
457 ev
->nesting
.hook_fn
= NULL
;
458 ev
->nesting
.hook_private
= NULL
;
463 static int tevent_common_context_constructor(struct tevent_context
*ev
)
467 ret
= tevent_init_globals();
474 ret
= pthread_mutex_init(&ev
->scheduled_mutex
, NULL
);
479 ret
= pthread_mutex_lock(&tevent_contexts_mutex
);
481 pthread_mutex_destroy(&ev
->scheduled_mutex
);
485 DLIST_ADD(tevent_contexts
, ev
);
487 ret
= pthread_mutex_unlock(&tevent_contexts_mutex
);
493 talloc_set_destructor(ev
, tevent_common_context_destructor
);
498 void tevent_common_check_double_free(TALLOC_CTX
*ptr
, const char *reason
)
500 void *parent_ptr
= talloc_parent(ptr
);
501 size_t parent_blocks
= talloc_total_blocks(parent_ptr
);
503 if (parent_ptr
!= NULL
&& parent_blocks
== 0) {
505 * This is an implicit talloc free, as we still have a parent
506 * but it's already being destroyed. Note that
507 * talloc_total_blocks(ptr) also just returns 0 if a
508 * talloc_free(ptr) is still in progress of freeing all
514 tevent_abort(NULL
, reason
);
518 create a event_context structure for a specific implementation.
519 This must be the first events call, and all subsequent calls pass
520 this event_context as the first element. Event handlers also
521 receive this as their first argument.
523 This function is for allowing third-party-applications to hook in gluecode
524 to their own event loop code, so that they can make async usage of our client libs
526 NOTE: use tevent_context_init() inside of samba!
528 struct tevent_context
*tevent_context_init_ops(TALLOC_CTX
*mem_ctx
,
529 const struct tevent_ops
*ops
,
530 void *additional_data
)
532 struct tevent_context
*ev
;
535 ev
= talloc_zero(mem_ctx
, struct tevent_context
);
536 if (!ev
) return NULL
;
538 ret
= tevent_common_context_constructor(ev
);
545 ev
->additional_data
= additional_data
;
547 ret
= ev
->ops
->context_init(ev
);
557 create a event_context structure. This must be the first events
558 call, and all subsequent calls pass this event_context as the first
559 element. Event handlers also receive this as their first argument.
561 struct tevent_context
*tevent_context_init_byname(TALLOC_CTX
*mem_ctx
,
564 const struct tevent_ops
*ops
;
566 ops
= tevent_find_ops_byname(name
);
571 return tevent_context_init_ops(mem_ctx
, ops
, NULL
);
576 create a event_context structure. This must be the first events
577 call, and all subsequent calls pass this event_context as the first
578 element. Event handlers also receive this as their first argument.
580 struct tevent_context
*tevent_context_init(TALLOC_CTX
*mem_ctx
)
582 return tevent_context_init_byname(mem_ctx
, NULL
);
587 return NULL on failure (memory allocation error)
589 struct tevent_fd
*_tevent_add_fd(struct tevent_context
*ev
,
593 tevent_fd_handler_t handler
,
595 const char *handler_name
,
596 const char *location
)
598 return ev
->ops
->add_fd(ev
, mem_ctx
, fd
, flags
, handler
, private_data
,
599 handler_name
, location
);
603 set a close function on the fd event
605 void tevent_fd_set_close_fn(struct tevent_fd
*fde
,
606 tevent_fd_close_fn_t close_fn
)
609 if (!fde
->event_ctx
) return;
610 fde
->event_ctx
->ops
->set_fd_close_fn(fde
, close_fn
);
613 static void tevent_fd_auto_close_fn(struct tevent_context
*ev
,
614 struct tevent_fd
*fde
,
621 void tevent_fd_set_auto_close(struct tevent_fd
*fde
)
623 tevent_fd_set_close_fn(fde
, tevent_fd_auto_close_fn
);
627 return the fd event flags
629 uint16_t tevent_fd_get_flags(struct tevent_fd
*fde
)
632 if (!fde
->event_ctx
) return 0;
633 return fde
->event_ctx
->ops
->get_fd_flags(fde
);
637 set the fd event flags
639 void tevent_fd_set_flags(struct tevent_fd
*fde
, uint16_t flags
)
642 if (!fde
->event_ctx
) return;
643 fde
->event_ctx
->ops
->set_fd_flags(fde
, flags
);
646 bool tevent_signal_support(struct tevent_context
*ev
)
648 if (ev
->ops
->add_signal
) {
654 static void (*tevent_abort_fn
)(const char *reason
);
656 void tevent_set_abort_fn(void (*abort_fn
)(const char *reason
))
658 tevent_abort_fn
= abort_fn
;
661 void tevent_abort(struct tevent_context
*ev
, const char *reason
)
664 tevent_debug(ev
, TEVENT_DEBUG_FATAL
,
665 "abort: %s\n", reason
);
668 if (!tevent_abort_fn
) {
672 tevent_abort_fn(reason
);
677 return NULL on failure
679 struct tevent_timer
*_tevent_add_timer(struct tevent_context
*ev
,
681 struct timeval next_event
,
682 tevent_timer_handler_t handler
,
684 const char *handler_name
,
685 const char *location
)
687 return ev
->ops
->add_timer(ev
, mem_ctx
, next_event
, handler
, private_data
,
688 handler_name
, location
);
692 allocate an immediate event
693 return NULL on failure (memory allocation error)
695 struct tevent_immediate
*_tevent_create_immediate(TALLOC_CTX
*mem_ctx
,
696 const char *location
)
698 struct tevent_immediate
*im
;
700 im
= talloc(mem_ctx
, struct tevent_immediate
);
701 if (im
== NULL
) return NULL
;
703 *im
= (struct tevent_immediate
) { .create_location
= location
};
709 schedule an immediate event
711 void _tevent_schedule_immediate(struct tevent_immediate
*im
,
712 struct tevent_context
*ev
,
713 tevent_immediate_handler_t handler
,
715 const char *handler_name
,
716 const char *location
)
718 ev
->ops
->schedule_immediate(im
, ev
, handler
, private_data
,
719 handler_name
, location
);
725 sa_flags are flags to sigaction(2)
727 return NULL on failure
729 struct tevent_signal
*_tevent_add_signal(struct tevent_context
*ev
,
733 tevent_signal_handler_t handler
,
735 const char *handler_name
,
736 const char *location
)
738 return ev
->ops
->add_signal(ev
, mem_ctx
, signum
, sa_flags
, handler
, private_data
,
739 handler_name
, location
);
742 void tevent_loop_allow_nesting(struct tevent_context
*ev
)
744 if (ev
->wrapper
.glue
!= NULL
) {
745 tevent_abort(ev
, "tevent_loop_allow_nesting() on wrapper");
749 if (ev
->wrapper
.list
!= NULL
) {
750 tevent_abort(ev
, "tevent_loop_allow_nesting() with wrapper");
754 ev
->nesting
.allowed
= true;
757 void tevent_loop_set_nesting_hook(struct tevent_context
*ev
,
758 tevent_nesting_hook hook
,
761 if (ev
->nesting
.hook_fn
&&
762 (ev
->nesting
.hook_fn
!= hook
||
763 ev
->nesting
.hook_private
!= private_data
)) {
764 /* the way the nesting hook code is currently written
765 we cannot support two different nesting hooks at the
767 tevent_abort(ev
, "tevent: Violation of nesting hook rules\n");
769 ev
->nesting
.hook_fn
= hook
;
770 ev
->nesting
.hook_private
= private_data
;
773 static void tevent_abort_nesting(struct tevent_context
*ev
, const char *location
)
777 reason
= talloc_asprintf(NULL
, "tevent_loop_once() nesting at %s",
780 reason
= "tevent_loop_once() nesting";
783 tevent_abort(ev
, reason
);
787 do a single event loop using the events defined in ev
789 int _tevent_loop_once(struct tevent_context
*ev
, const char *location
)
792 void *nesting_stack_ptr
= NULL
;
796 if (ev
->nesting
.level
> 1) {
797 if (!ev
->nesting
.allowed
) {
798 tevent_abort_nesting(ev
, location
);
803 if (ev
->nesting
.level
> 0) {
804 if (ev
->nesting
.hook_fn
) {
806 ret2
= ev
->nesting
.hook_fn(ev
,
807 ev
->nesting
.hook_private
,
810 (void *)&nesting_stack_ptr
,
819 tevent_trace_point_callback(ev
, TEVENT_TRACE_BEFORE_LOOP_ONCE
);
820 ret
= ev
->ops
->loop_once(ev
, location
);
821 tevent_trace_point_callback(ev
, TEVENT_TRACE_AFTER_LOOP_ONCE
);
823 /* New event (and request) will always start with call depth 0. */
824 tevent_thread_call_depth_notify(TEVENT_CALL_FLOW_REQ_RESET
,
829 if (ev
->nesting
.level
> 0) {
830 if (ev
->nesting
.hook_fn
) {
832 ret2
= ev
->nesting
.hook_fn(ev
,
833 ev
->nesting
.hook_private
,
836 (void *)&nesting_stack_ptr
,
851 this is a performance optimization for the samba4 nested event loop problems
853 int _tevent_loop_until(struct tevent_context
*ev
,
854 bool (*finished
)(void *private_data
),
856 const char *location
)
859 void *nesting_stack_ptr
= NULL
;
863 if (ev
->nesting
.level
> 1) {
864 if (!ev
->nesting
.allowed
) {
865 tevent_abort_nesting(ev
, location
);
870 if (ev
->nesting
.level
> 0) {
871 if (ev
->nesting
.hook_fn
) {
873 ret2
= ev
->nesting
.hook_fn(ev
,
874 ev
->nesting
.hook_private
,
877 (void *)&nesting_stack_ptr
,
886 while (!finished(private_data
)) {
887 tevent_trace_point_callback(ev
, TEVENT_TRACE_BEFORE_LOOP_ONCE
);
888 ret
= ev
->ops
->loop_once(ev
, location
);
889 tevent_trace_point_callback(ev
, TEVENT_TRACE_AFTER_LOOP_ONCE
);
895 if (ev
->nesting
.level
> 0) {
896 if (ev
->nesting
.hook_fn
) {
898 ret2
= ev
->nesting
.hook_fn(ev
,
899 ev
->nesting
.hook_private
,
902 (void *)&nesting_stack_ptr
,
916 bool tevent_common_have_events(struct tevent_context
*ev
)
918 if (ev
->fd_events
!= NULL
) {
919 if (ev
->fd_events
!= ev
->wakeup_fde
) {
922 if (ev
->fd_events
->next
!= NULL
) {
927 * At this point we just have the wakeup pipe event as
928 * the only fd_event. That one does not count as a
929 * regular event, so look at the other event types.
933 return ((ev
->timer_events
!= NULL
) ||
934 (ev
->immediate_events
!= NULL
) ||
935 (ev
->signal_events
!= NULL
));
939 return on failure or (with 0) if all fd events are removed
941 int tevent_common_loop_wait(struct tevent_context
*ev
,
942 const char *location
)
945 * loop as long as we have events pending
947 while (tevent_common_have_events(ev
)) {
949 ret
= _tevent_loop_once(ev
, location
);
951 tevent_debug(ev
, TEVENT_DEBUG_FATAL
,
952 "_tevent_loop_once() failed: %d - %s\n",
953 ret
, strerror(errno
));
958 tevent_debug(ev
, TEVENT_DEBUG_WARNING
,
959 "tevent_common_loop_wait() out of events\n");
964 return on failure or (with 0) if all fd events are removed
966 int _tevent_loop_wait(struct tevent_context
*ev
, const char *location
)
968 return ev
->ops
->loop_wait(ev
, location
);
973 re-initialise a tevent context. This leaves you with the same
974 event context, but all events are wiped and the structure is
975 re-initialised. This is most useful after a fork()
977 zero is returned on success, non-zero on failure
979 int tevent_re_initialise(struct tevent_context
*ev
)
981 tevent_common_context_destructor(ev
);
983 tevent_common_context_constructor(ev
);
985 return ev
->ops
->context_init(ev
);
988 static void wakeup_pipe_handler(struct tevent_context
*ev
,
989 struct tevent_fd
*fde
,
990 uint16_t flags
, void *_private
)
996 * This is the boilerplate for eventfd, but it works
997 * for pipes too. And as we don't care about the data
998 * we read, we're fine.
1001 ret
= read(fde
->fd
, &val
, sizeof(val
));
1002 } while (ret
== -1 && errno
== EINTR
);
1006 * Initialize the wakeup pipe and pipe fde
1009 int tevent_common_wakeup_init(struct tevent_context
*ev
)
1013 if (ev
->wakeup_fde
!= NULL
) {
1018 ret
= eventfd(0, EFD_NONBLOCK
);
1022 read_fd
= ev
->wakeup_fd
= ret
;
1026 ret
= pipe(pipe_fds
);
1030 ev
->wakeup_fd
= pipe_fds
[1];
1031 ev
->wakeup_read_fd
= pipe_fds
[0];
1033 ev_set_blocking(ev
->wakeup_fd
, false);
1034 ev_set_blocking(ev
->wakeup_read_fd
, false);
1036 read_fd
= ev
->wakeup_read_fd
;
1040 ev
->wakeup_fde
= tevent_add_fd(ev
, ev
, read_fd
, TEVENT_FD_READ
,
1041 wakeup_pipe_handler
, NULL
);
1042 if (ev
->wakeup_fde
== NULL
) {
1043 close(ev
->wakeup_fd
);
1044 #ifndef HAVE_EVENTFD
1045 close(ev
->wakeup_read_fd
);
1053 int tevent_common_wakeup_fd(int fd
)
1060 ret
= write(fd
, &val
, sizeof(val
));
1063 ret
= write(fd
, &c
, 1);
1065 } while ((ret
== -1) && (errno
== EINTR
));
1070 int tevent_common_wakeup(struct tevent_context
*ev
)
1072 if (ev
->wakeup_fde
== NULL
) {
1076 return tevent_common_wakeup_fd(ev
->wakeup_fd
);
1079 static void tevent_common_wakeup_fini(struct tevent_context
*ev
)
1081 if (ev
->wakeup_fde
== NULL
) {
1085 TALLOC_FREE(ev
->wakeup_fde
);
1087 close(ev
->wakeup_fd
);
1088 #ifndef HAVE_EVENTFD
1089 close(ev
->wakeup_read_fd
);