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)
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
;
171 tevent_backend_init();
173 for (e
=tevent_backends
;e
;e
=e
->next
) {
177 list
= talloc_zero_array(mem_ctx
, const char *, idx
+1);
183 for (e
=tevent_backends
;e
;e
=e
->next
) {
184 list
[idx
] = talloc_strdup(list
, e
->name
);
185 if (list
[idx
] == NULL
) {
195 static void tevent_common_wakeup_fini(struct tevent_context
*ev
);
199 static pthread_mutex_t tevent_contexts_mutex
= PTHREAD_MUTEX_INITIALIZER
;
200 static struct tevent_context
*tevent_contexts
= NULL
;
201 static pthread_once_t tevent_atfork_initialized
= PTHREAD_ONCE_INIT
;
203 static void tevent_atfork_prepare(void)
205 struct tevent_context
*ev
;
208 ret
= pthread_mutex_lock(&tevent_contexts_mutex
);
213 for (ev
= tevent_contexts
; ev
!= NULL
; ev
= ev
->next
) {
214 struct tevent_threaded_context
*tctx
;
216 for (tctx
= ev
->threaded_contexts
; tctx
!= NULL
;
218 ret
= pthread_mutex_lock(&tctx
->event_ctx_mutex
);
220 tevent_abort(ev
, "pthread_mutex_lock failed");
224 ret
= pthread_mutex_lock(&ev
->scheduled_mutex
);
226 tevent_abort(ev
, "pthread_mutex_lock failed");
231 static void tevent_atfork_parent(void)
233 struct tevent_context
*ev
;
236 for (ev
= DLIST_TAIL(tevent_contexts
); ev
!= NULL
;
237 ev
= DLIST_PREV(ev
)) {
238 struct tevent_threaded_context
*tctx
;
240 ret
= pthread_mutex_unlock(&ev
->scheduled_mutex
);
242 tevent_abort(ev
, "pthread_mutex_unlock failed");
245 for (tctx
= DLIST_TAIL(ev
->threaded_contexts
); tctx
!= NULL
;
246 tctx
= DLIST_PREV(tctx
)) {
247 ret
= pthread_mutex_unlock(&tctx
->event_ctx_mutex
);
250 ev
, "pthread_mutex_unlock failed");
255 ret
= pthread_mutex_unlock(&tevent_contexts_mutex
);
261 static void tevent_atfork_child(void)
263 struct tevent_context
*ev
;
266 for (ev
= DLIST_TAIL(tevent_contexts
); ev
!= NULL
;
267 ev
= DLIST_PREV(ev
)) {
268 struct tevent_threaded_context
*tctx
;
270 for (tctx
= DLIST_TAIL(ev
->threaded_contexts
); tctx
!= NULL
;
271 tctx
= DLIST_PREV(tctx
)) {
272 tctx
->event_ctx
= NULL
;
274 ret
= pthread_mutex_unlock(&tctx
->event_ctx_mutex
);
277 ev
, "pthread_mutex_unlock failed");
281 ev
->threaded_contexts
= NULL
;
283 ret
= pthread_mutex_unlock(&ev
->scheduled_mutex
);
285 tevent_abort(ev
, "pthread_mutex_unlock failed");
289 ret
= pthread_mutex_unlock(&tevent_contexts_mutex
);
295 static void tevent_prep_atfork(void)
299 ret
= pthread_atfork(tevent_atfork_prepare
,
300 tevent_atfork_parent
,
301 tevent_atfork_child
);
309 int tevent_common_context_destructor(struct tevent_context
*ev
)
311 struct tevent_fd
*fd
, *fn
;
312 struct tevent_timer
*te
, *tn
;
313 struct tevent_immediate
*ie
, *in
;
314 struct tevent_signal
*se
, *sn
;
315 struct tevent_wrapper_glue
*gl
, *gn
;
320 if (ev
->wrapper
.glue
!= NULL
) {
322 "tevent_common_context_destructor() active on wrapper");
326 ret
= pthread_mutex_lock(&tevent_contexts_mutex
);
331 DLIST_REMOVE(tevent_contexts
, ev
);
333 ret
= pthread_mutex_unlock(&tevent_contexts_mutex
);
338 while (ev
->threaded_contexts
!= NULL
) {
339 struct tevent_threaded_context
*tctx
= ev
->threaded_contexts
;
341 ret
= pthread_mutex_lock(&tctx
->event_ctx_mutex
);
347 * Indicate to the thread that the tevent_context is
348 * gone. The counterpart of this is in
349 * _tevent_threaded_schedule_immediate, there we read
350 * this under the threaded_context's mutex.
353 tctx
->event_ctx
= NULL
;
355 ret
= pthread_mutex_unlock(&tctx
->event_ctx_mutex
);
360 DLIST_REMOVE(ev
->threaded_contexts
, tctx
);
363 ret
= pthread_mutex_destroy(&ev
->scheduled_mutex
);
369 for (gl
= ev
->wrapper
.list
; gl
; gl
= gn
) {
373 DLIST_REMOVE(ev
->wrapper
.list
, gl
);
376 tevent_common_wakeup_fini(ev
);
378 for (fd
= ev
->fd_events
; fd
; fd
= fn
) {
380 tevent_trace_fd_callback(fd
->event_ctx
, fd
, TEVENT_EVENT_TRACE_DETACH
);
382 fd
->event_ctx
= NULL
;
383 DLIST_REMOVE(ev
->fd_events
, fd
);
386 ev
->last_zero_timer
= NULL
;
387 for (te
= ev
->timer_events
; te
; te
= tn
) {
389 tevent_trace_timer_callback(te
->event_ctx
, te
, TEVENT_EVENT_TRACE_DETACH
);
391 te
->event_ctx
= NULL
;
392 DLIST_REMOVE(ev
->timer_events
, te
);
395 for (ie
= ev
->immediate_events
; ie
; ie
= in
) {
397 tevent_trace_immediate_callback(ie
->event_ctx
, ie
, TEVENT_EVENT_TRACE_DETACH
);
399 ie
->event_ctx
= NULL
;
400 ie
->cancel_fn
= NULL
;
401 DLIST_REMOVE(ev
->immediate_events
, ie
);
404 for (se
= ev
->signal_events
; se
; se
= sn
) {
406 tevent_trace_signal_callback(se
->event_ctx
, se
, TEVENT_EVENT_TRACE_DETACH
);
408 se
->event_ctx
= NULL
;
409 DLIST_REMOVE(ev
->signal_events
, se
);
411 * This is important, Otherwise signals
412 * are handled twice in child. eg, SIGHUP.
413 * one added in parent, and another one in
414 * the child. -- BoYang
416 tevent_cleanup_pending_signal_handlers(se
);
419 /* removing nesting hook or we get an abort when nesting is
420 * not allowed. -- SSS
421 * Note that we need to leave the allowed flag at its current
422 * value, otherwise the use in tevent_re_initialise() will
423 * leave the event context with allowed forced to false, which
424 * will break users that expect nesting to be allowed
426 ev
->nesting
.level
= 0;
427 ev
->nesting
.hook_fn
= NULL
;
428 ev
->nesting
.hook_private
= NULL
;
433 static int tevent_common_context_constructor(struct tevent_context
*ev
)
439 ret
= pthread_once(&tevent_atfork_initialized
, tevent_prep_atfork
);
444 ret
= pthread_mutex_init(&ev
->scheduled_mutex
, NULL
);
449 ret
= pthread_mutex_lock(&tevent_contexts_mutex
);
451 pthread_mutex_destroy(&ev
->scheduled_mutex
);
455 DLIST_ADD(tevent_contexts
, ev
);
457 ret
= pthread_mutex_unlock(&tevent_contexts_mutex
);
463 talloc_set_destructor(ev
, tevent_common_context_destructor
);
468 void tevent_common_check_double_free(TALLOC_CTX
*ptr
, const char *reason
)
470 void *parent_ptr
= talloc_parent(ptr
);
471 size_t parent_blocks
= talloc_total_blocks(parent_ptr
);
473 if (parent_ptr
!= NULL
&& parent_blocks
== 0) {
475 * This is an implicit talloc free, as we still have a parent
476 * but it's already being destroyed. Note that
477 * talloc_total_blocks(ptr) also just returns 0 if a
478 * talloc_free(ptr) is still in progress of freeing all
484 tevent_abort(NULL
, reason
);
488 create a event_context structure for a specific implemementation.
489 This must be the first events call, and all subsequent calls pass
490 this event_context as the first element. Event handlers also
491 receive this as their first argument.
493 This function is for allowing third-party-applications to hook in gluecode
494 to their own event loop code, so that they can make async usage of our client libs
496 NOTE: use tevent_context_init() inside of samba!
498 struct tevent_context
*tevent_context_init_ops(TALLOC_CTX
*mem_ctx
,
499 const struct tevent_ops
*ops
,
500 void *additional_data
)
502 struct tevent_context
*ev
;
505 ev
= talloc_zero(mem_ctx
, struct tevent_context
);
506 if (!ev
) return NULL
;
508 ret
= tevent_common_context_constructor(ev
);
515 ev
->additional_data
= additional_data
;
517 ret
= ev
->ops
->context_init(ev
);
527 create a event_context structure. This must be the first events
528 call, and all subsequent calls pass this event_context as the first
529 element. Event handlers also receive this as their first argument.
531 struct tevent_context
*tevent_context_init_byname(TALLOC_CTX
*mem_ctx
,
534 const struct tevent_ops
*ops
;
536 ops
= tevent_find_ops_byname(name
);
541 return tevent_context_init_ops(mem_ctx
, ops
, NULL
);
546 create a event_context structure. This must be the first events
547 call, and all subsequent calls pass this event_context as the first
548 element. Event handlers also receive this as their first argument.
550 struct tevent_context
*tevent_context_init(TALLOC_CTX
*mem_ctx
)
552 return tevent_context_init_byname(mem_ctx
, NULL
);
557 return NULL on failure (memory allocation error)
559 struct tevent_fd
*_tevent_add_fd(struct tevent_context
*ev
,
563 tevent_fd_handler_t handler
,
565 const char *handler_name
,
566 const char *location
)
568 return ev
->ops
->add_fd(ev
, mem_ctx
, fd
, flags
, handler
, private_data
,
569 handler_name
, location
);
573 set a close function on the fd event
575 void tevent_fd_set_close_fn(struct tevent_fd
*fde
,
576 tevent_fd_close_fn_t close_fn
)
579 if (!fde
->event_ctx
) return;
580 fde
->event_ctx
->ops
->set_fd_close_fn(fde
, close_fn
);
583 static void tevent_fd_auto_close_fn(struct tevent_context
*ev
,
584 struct tevent_fd
*fde
,
591 void tevent_fd_set_auto_close(struct tevent_fd
*fde
)
593 tevent_fd_set_close_fn(fde
, tevent_fd_auto_close_fn
);
597 return the fd event flags
599 uint16_t tevent_fd_get_flags(struct tevent_fd
*fde
)
602 if (!fde
->event_ctx
) return 0;
603 return fde
->event_ctx
->ops
->get_fd_flags(fde
);
607 set the fd event flags
609 void tevent_fd_set_flags(struct tevent_fd
*fde
, uint16_t flags
)
612 if (!fde
->event_ctx
) return;
613 fde
->event_ctx
->ops
->set_fd_flags(fde
, flags
);
616 bool tevent_signal_support(struct tevent_context
*ev
)
618 if (ev
->ops
->add_signal
) {
624 static void (*tevent_abort_fn
)(const char *reason
);
626 void tevent_set_abort_fn(void (*abort_fn
)(const char *reason
))
628 tevent_abort_fn
= abort_fn
;
631 void tevent_abort(struct tevent_context
*ev
, const char *reason
)
634 tevent_debug(ev
, TEVENT_DEBUG_FATAL
,
635 "abort: %s\n", reason
);
638 if (!tevent_abort_fn
) {
642 tevent_abort_fn(reason
);
647 return NULL on failure
649 struct tevent_timer
*_tevent_add_timer(struct tevent_context
*ev
,
651 struct timeval next_event
,
652 tevent_timer_handler_t handler
,
654 const char *handler_name
,
655 const char *location
)
657 return ev
->ops
->add_timer(ev
, mem_ctx
, next_event
, handler
, private_data
,
658 handler_name
, location
);
662 allocate an immediate event
663 return NULL on failure (memory allocation error)
665 struct tevent_immediate
*_tevent_create_immediate(TALLOC_CTX
*mem_ctx
,
666 const char *location
)
668 struct tevent_immediate
*im
;
670 im
= talloc(mem_ctx
, struct tevent_immediate
);
671 if (im
== NULL
) return NULL
;
673 *im
= (struct tevent_immediate
) { .create_location
= location
};
679 schedule an immediate event
681 void _tevent_schedule_immediate(struct tevent_immediate
*im
,
682 struct tevent_context
*ev
,
683 tevent_immediate_handler_t handler
,
685 const char *handler_name
,
686 const char *location
)
688 ev
->ops
->schedule_immediate(im
, ev
, handler
, private_data
,
689 handler_name
, location
);
695 sa_flags are flags to sigaction(2)
697 return NULL on failure
699 struct tevent_signal
*_tevent_add_signal(struct tevent_context
*ev
,
703 tevent_signal_handler_t handler
,
705 const char *handler_name
,
706 const char *location
)
708 return ev
->ops
->add_signal(ev
, mem_ctx
, signum
, sa_flags
, handler
, private_data
,
709 handler_name
, location
);
712 void tevent_loop_allow_nesting(struct tevent_context
*ev
)
714 if (ev
->wrapper
.glue
!= NULL
) {
715 tevent_abort(ev
, "tevent_loop_allow_nesting() on wrapper");
719 if (ev
->wrapper
.list
!= NULL
) {
720 tevent_abort(ev
, "tevent_loop_allow_nesting() with wrapper");
724 ev
->nesting
.allowed
= true;
727 void tevent_loop_set_nesting_hook(struct tevent_context
*ev
,
728 tevent_nesting_hook hook
,
731 if (ev
->nesting
.hook_fn
&&
732 (ev
->nesting
.hook_fn
!= hook
||
733 ev
->nesting
.hook_private
!= private_data
)) {
734 /* the way the nesting hook code is currently written
735 we cannot support two different nesting hooks at the
737 tevent_abort(ev
, "tevent: Violation of nesting hook rules\n");
739 ev
->nesting
.hook_fn
= hook
;
740 ev
->nesting
.hook_private
= private_data
;
743 static void tevent_abort_nesting(struct tevent_context
*ev
, const char *location
)
747 reason
= talloc_asprintf(NULL
, "tevent_loop_once() nesting at %s",
750 reason
= "tevent_loop_once() nesting";
753 tevent_abort(ev
, reason
);
757 do a single event loop using the events defined in ev
759 int _tevent_loop_once(struct tevent_context
*ev
, const char *location
)
762 void *nesting_stack_ptr
= NULL
;
766 if (ev
->nesting
.level
> 1) {
767 if (!ev
->nesting
.allowed
) {
768 tevent_abort_nesting(ev
, location
);
773 if (ev
->nesting
.level
> 0) {
774 if (ev
->nesting
.hook_fn
) {
776 ret2
= ev
->nesting
.hook_fn(ev
,
777 ev
->nesting
.hook_private
,
780 (void *)&nesting_stack_ptr
,
789 tevent_trace_point_callback(ev
, TEVENT_TRACE_BEFORE_LOOP_ONCE
);
790 ret
= ev
->ops
->loop_once(ev
, location
);
791 tevent_trace_point_callback(ev
, TEVENT_TRACE_AFTER_LOOP_ONCE
);
793 if (ev
->nesting
.level
> 0) {
794 if (ev
->nesting
.hook_fn
) {
796 ret2
= ev
->nesting
.hook_fn(ev
,
797 ev
->nesting
.hook_private
,
800 (void *)&nesting_stack_ptr
,
815 this is a performance optimization for the samba4 nested event loop problems
817 int _tevent_loop_until(struct tevent_context
*ev
,
818 bool (*finished
)(void *private_data
),
820 const char *location
)
823 void *nesting_stack_ptr
= NULL
;
827 if (ev
->nesting
.level
> 1) {
828 if (!ev
->nesting
.allowed
) {
829 tevent_abort_nesting(ev
, location
);
834 if (ev
->nesting
.level
> 0) {
835 if (ev
->nesting
.hook_fn
) {
837 ret2
= ev
->nesting
.hook_fn(ev
,
838 ev
->nesting
.hook_private
,
841 (void *)&nesting_stack_ptr
,
850 while (!finished(private_data
)) {
851 tevent_trace_point_callback(ev
, TEVENT_TRACE_BEFORE_LOOP_ONCE
);
852 ret
= ev
->ops
->loop_once(ev
, location
);
853 tevent_trace_point_callback(ev
, TEVENT_TRACE_AFTER_LOOP_ONCE
);
859 if (ev
->nesting
.level
> 0) {
860 if (ev
->nesting
.hook_fn
) {
862 ret2
= ev
->nesting
.hook_fn(ev
,
863 ev
->nesting
.hook_private
,
866 (void *)&nesting_stack_ptr
,
880 bool tevent_common_have_events(struct tevent_context
*ev
)
882 if (ev
->fd_events
!= NULL
) {
883 if (ev
->fd_events
!= ev
->wakeup_fde
) {
886 if (ev
->fd_events
->next
!= NULL
) {
891 * At this point we just have the wakeup pipe event as
892 * the only fd_event. That one does not count as a
893 * regular event, so look at the other event types.
897 return ((ev
->timer_events
!= NULL
) ||
898 (ev
->immediate_events
!= NULL
) ||
899 (ev
->signal_events
!= NULL
));
903 return on failure or (with 0) if all fd events are removed
905 int tevent_common_loop_wait(struct tevent_context
*ev
,
906 const char *location
)
909 * loop as long as we have events pending
911 while (tevent_common_have_events(ev
)) {
913 ret
= _tevent_loop_once(ev
, location
);
915 tevent_debug(ev
, TEVENT_DEBUG_FATAL
,
916 "_tevent_loop_once() failed: %d - %s\n",
917 ret
, strerror(errno
));
922 tevent_debug(ev
, TEVENT_DEBUG_WARNING
,
923 "tevent_common_loop_wait() out of events\n");
928 return on failure or (with 0) if all fd events are removed
930 int _tevent_loop_wait(struct tevent_context
*ev
, const char *location
)
932 return ev
->ops
->loop_wait(ev
, location
);
937 re-initialise a tevent context. This leaves you with the same
938 event context, but all events are wiped and the structure is
939 re-initialised. This is most useful after a fork()
941 zero is returned on success, non-zero on failure
943 int tevent_re_initialise(struct tevent_context
*ev
)
945 tevent_common_context_destructor(ev
);
947 tevent_common_context_constructor(ev
);
949 return ev
->ops
->context_init(ev
);
952 static void wakeup_pipe_handler(struct tevent_context
*ev
,
953 struct tevent_fd
*fde
,
954 uint16_t flags
, void *_private
)
960 * This is the boilerplate for eventfd, but it works
961 * for pipes too. And as we don't care about the data
962 * we read, we're fine.
965 ret
= read(fde
->fd
, &val
, sizeof(val
));
966 } while (ret
== -1 && errno
== EINTR
);
970 * Initialize the wakeup pipe and pipe fde
973 int tevent_common_wakeup_init(struct tevent_context
*ev
)
977 if (ev
->wakeup_fde
!= NULL
) {
982 ret
= eventfd(0, EFD_NONBLOCK
);
986 read_fd
= ev
->wakeup_fd
= ret
;
990 ret
= pipe(pipe_fds
);
994 ev
->wakeup_fd
= pipe_fds
[1];
995 ev
->wakeup_read_fd
= pipe_fds
[0];
997 ev_set_blocking(ev
->wakeup_fd
, false);
998 ev_set_blocking(ev
->wakeup_read_fd
, false);
1000 read_fd
= ev
->wakeup_read_fd
;
1004 ev
->wakeup_fde
= tevent_add_fd(ev
, ev
, read_fd
, TEVENT_FD_READ
,
1005 wakeup_pipe_handler
, NULL
);
1006 if (ev
->wakeup_fde
== NULL
) {
1007 close(ev
->wakeup_fd
);
1008 #ifndef HAVE_EVENTFD
1009 close(ev
->wakeup_read_fd
);
1017 int tevent_common_wakeup_fd(int fd
)
1024 ret
= write(fd
, &val
, sizeof(val
));
1027 ret
= write(fd
, &c
, 1);
1029 } while ((ret
== -1) && (errno
== EINTR
));
1034 int tevent_common_wakeup(struct tevent_context
*ev
)
1036 if (ev
->wakeup_fde
== NULL
) {
1040 return tevent_common_wakeup_fd(ev
->wakeup_fd
);
1043 static void tevent_common_wakeup_fini(struct tevent_context
*ev
)
1045 if (ev
->wakeup_fde
== NULL
) {
1049 TALLOC_FREE(ev
->wakeup_fde
);
1051 close(ev
->wakeup_fd
);
1052 #ifndef HAVE_EVENTFD
1053 close(ev
->wakeup_read_fd
);