1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-10 12:58:35 +03:00

tevent: Sync to tevent 0.9.18 from upstream

(This used to be ctdb commit 82d61f77c01df0fbb42743593937b175ce22a445)
This commit is contained in:
Amitay Isaacs 2013-05-29 14:12:14 +10:00
parent 4c1dc871b9
commit 2afa275a68
28 changed files with 3806 additions and 750 deletions

View File

@ -0,0 +1,73 @@
_tevent_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
_tevent_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
_tevent_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
_tevent_create_immediate: struct tevent_immediate *(TALLOC_CTX *, const char *)
_tevent_loop_once: int (struct tevent_context *, const char *)
_tevent_loop_until: int (struct tevent_context *, bool (*)(void *), void *, const char *)
_tevent_loop_wait: int (struct tevent_context *, const char *)
_tevent_queue_create: struct tevent_queue *(TALLOC_CTX *, const char *, const char *)
_tevent_req_callback_data: void *(struct tevent_req *)
_tevent_req_cancel: bool (struct tevent_req *, const char *)
_tevent_req_create: struct tevent_req *(TALLOC_CTX *, void *, size_t, const char *, const char *)
_tevent_req_data: void *(struct tevent_req *)
_tevent_req_done: void (struct tevent_req *, const char *)
_tevent_req_error: bool (struct tevent_req *, uint64_t, const char *)
_tevent_req_nomem: bool (const void *, struct tevent_req *, const char *)
_tevent_req_notify_callback: void (struct tevent_req *, const char *)
_tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
tevent_backend_list: const char **(TALLOC_CTX *)
tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *)
tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
tevent_common_check_signal: int (struct tevent_context *)
tevent_common_context_destructor: int (struct tevent_context *)
tevent_common_fd_destructor: int (struct tevent_fd *)
tevent_common_fd_get_flags: uint16_t (struct tevent_fd *)
tevent_common_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
tevent_common_fd_set_flags: void (struct tevent_fd *, uint16_t)
tevent_common_loop_immediate: bool (struct tevent_context *)
tevent_common_loop_timer_delay: struct timeval (struct tevent_context *)
tevent_common_loop_wait: int (struct tevent_context *, const char *)
tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
tevent_context_init: struct tevent_context *(TALLOC_CTX *)
tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *)
tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...)
tevent_fd_get_flags: uint16_t (struct tevent_fd *)
tevent_fd_set_auto_close: void (struct tevent_fd *)
tevent_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
tevent_fd_set_flags: void (struct tevent_fd *, uint16_t)
tevent_loop_allow_nesting: void (struct tevent_context *)
tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *)
tevent_queue_add: bool (struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
tevent_queue_length: size_t (struct tevent_queue *)
tevent_queue_start: void (struct tevent_queue *)
tevent_queue_stop: void (struct tevent_queue *)
tevent_re_initialise: int (struct tevent_context *)
tevent_register_backend: bool (const char *, const struct tevent_ops *)
tevent_req_default_print: char *(struct tevent_req *, TALLOC_CTX *)
tevent_req_is_error: bool (struct tevent_req *, enum tevent_req_state *, uint64_t *)
tevent_req_is_in_progress: bool (struct tevent_req *)
tevent_req_poll: bool (struct tevent_req *, struct tevent_context *)
tevent_req_post: struct tevent_req *(struct tevent_req *, struct tevent_context *)
tevent_req_print: char *(TALLOC_CTX *, struct tevent_req *)
tevent_req_received: void (struct tevent_req *)
tevent_req_set_callback: void (struct tevent_req *, tevent_req_fn, void *)
tevent_req_set_cancel_fn: void (struct tevent_req *, tevent_req_cancel_fn)
tevent_req_set_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval)
tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn)
tevent_set_abort_fn: void (void (*)(const char *))
tevent_set_debug: int (struct tevent_context *, void (*)(void *, enum tevent_debug_level, const char *, va_list), void *)
tevent_set_debug_stderr: int (struct tevent_context *)
tevent_set_default_backend: void (const char *)
tevent_signal_support: bool (struct tevent_context *)
tevent_timeval_add: struct timeval (const struct timeval *, uint32_t, uint32_t)
tevent_timeval_compare: int (const struct timeval *, const struct timeval *)
tevent_timeval_current: struct timeval (void)
tevent_timeval_current_ofs: struct timeval (uint32_t, uint32_t)
tevent_timeval_is_zero: bool (const struct timeval *)
tevent_timeval_set: struct timeval (uint32_t, uint32_t)
tevent_timeval_until: struct timeval (const struct timeval *, const struct timeval *)
tevent_timeval_zero: struct timeval (void)
tevent_wakeup_recv: bool (struct tevent_req *)
tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval)

View File

@ -0,0 +1,73 @@
_tevent_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
_tevent_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
_tevent_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
_tevent_create_immediate: struct tevent_immediate *(TALLOC_CTX *, const char *)
_tevent_loop_once: int (struct tevent_context *, const char *)
_tevent_loop_until: int (struct tevent_context *, bool (*)(void *), void *, const char *)
_tevent_loop_wait: int (struct tevent_context *, const char *)
_tevent_queue_create: struct tevent_queue *(TALLOC_CTX *, const char *, const char *)
_tevent_req_callback_data: void *(struct tevent_req *)
_tevent_req_cancel: bool (struct tevent_req *, const char *)
_tevent_req_create: struct tevent_req *(TALLOC_CTX *, void *, size_t, const char *, const char *)
_tevent_req_data: void *(struct tevent_req *)
_tevent_req_done: void (struct tevent_req *, const char *)
_tevent_req_error: bool (struct tevent_req *, uint64_t, const char *)
_tevent_req_nomem: bool (const void *, struct tevent_req *, const char *)
_tevent_req_notify_callback: void (struct tevent_req *, const char *)
_tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
tevent_backend_list: const char **(TALLOC_CTX *)
tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *)
tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
tevent_common_check_signal: int (struct tevent_context *)
tevent_common_context_destructor: int (struct tevent_context *)
tevent_common_fd_destructor: int (struct tevent_fd *)
tevent_common_fd_get_flags: uint16_t (struct tevent_fd *)
tevent_common_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
tevent_common_fd_set_flags: void (struct tevent_fd *, uint16_t)
tevent_common_loop_immediate: bool (struct tevent_context *)
tevent_common_loop_timer_delay: struct timeval (struct tevent_context *)
tevent_common_loop_wait: int (struct tevent_context *, const char *)
tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
tevent_context_init: struct tevent_context *(TALLOC_CTX *)
tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *)
tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...)
tevent_fd_get_flags: uint16_t (struct tevent_fd *)
tevent_fd_set_auto_close: void (struct tevent_fd *)
tevent_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
tevent_fd_set_flags: void (struct tevent_fd *, uint16_t)
tevent_loop_allow_nesting: void (struct tevent_context *)
tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *)
tevent_queue_add: bool (struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
tevent_queue_length: size_t (struct tevent_queue *)
tevent_queue_start: void (struct tevent_queue *)
tevent_queue_stop: void (struct tevent_queue *)
tevent_re_initialise: int (struct tevent_context *)
tevent_register_backend: bool (const char *, const struct tevent_ops *)
tevent_req_default_print: char *(struct tevent_req *, TALLOC_CTX *)
tevent_req_is_error: bool (struct tevent_req *, enum tevent_req_state *, uint64_t *)
tevent_req_is_in_progress: bool (struct tevent_req *)
tevent_req_poll: bool (struct tevent_req *, struct tevent_context *)
tevent_req_post: struct tevent_req *(struct tevent_req *, struct tevent_context *)
tevent_req_print: char *(TALLOC_CTX *, struct tevent_req *)
tevent_req_received: void (struct tevent_req *)
tevent_req_set_callback: void (struct tevent_req *, tevent_req_fn, void *)
tevent_req_set_cancel_fn: void (struct tevent_req *, tevent_req_cancel_fn)
tevent_req_set_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval)
tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn)
tevent_set_abort_fn: void (void (*)(const char *))
tevent_set_debug: int (struct tevent_context *, void (*)(void *, enum tevent_debug_level, const char *, va_list), void *)
tevent_set_debug_stderr: int (struct tevent_context *)
tevent_set_default_backend: void (const char *)
tevent_signal_support: bool (struct tevent_context *)
tevent_timeval_add: struct timeval (const struct timeval *, uint32_t, uint32_t)
tevent_timeval_compare: int (const struct timeval *, const struct timeval *)
tevent_timeval_current: struct timeval (void)
tevent_timeval_current_ofs: struct timeval (uint32_t, uint32_t)
tevent_timeval_is_zero: bool (const struct timeval *)
tevent_timeval_set: struct timeval (uint32_t, uint32_t)
tevent_timeval_until: struct timeval (const struct timeval *, const struct timeval *)
tevent_timeval_zero: struct timeval (void)
tevent_wakeup_recv: bool (struct tevent_req *)
tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval)

View File

@ -0,0 +1,74 @@
_tevent_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
_tevent_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
_tevent_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
_tevent_create_immediate: struct tevent_immediate *(TALLOC_CTX *, const char *)
_tevent_loop_once: int (struct tevent_context *, const char *)
_tevent_loop_until: int (struct tevent_context *, bool (*)(void *), void *, const char *)
_tevent_loop_wait: int (struct tevent_context *, const char *)
_tevent_queue_create: struct tevent_queue *(TALLOC_CTX *, const char *, const char *)
_tevent_req_callback_data: void *(struct tevent_req *)
_tevent_req_cancel: bool (struct tevent_req *, const char *)
_tevent_req_create: struct tevent_req *(TALLOC_CTX *, void *, size_t, const char *, const char *)
_tevent_req_data: void *(struct tevent_req *)
_tevent_req_done: void (struct tevent_req *, const char *)
_tevent_req_error: bool (struct tevent_req *, uint64_t, const char *)
_tevent_req_nomem: bool (const void *, struct tevent_req *, const char *)
_tevent_req_notify_callback: void (struct tevent_req *, const char *)
_tevent_req_oom: void (struct tevent_req *, const char *)
_tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
tevent_backend_list: const char **(TALLOC_CTX *)
tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *)
tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
tevent_common_check_signal: int (struct tevent_context *)
tevent_common_context_destructor: int (struct tevent_context *)
tevent_common_fd_destructor: int (struct tevent_fd *)
tevent_common_fd_get_flags: uint16_t (struct tevent_fd *)
tevent_common_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
tevent_common_fd_set_flags: void (struct tevent_fd *, uint16_t)
tevent_common_loop_immediate: bool (struct tevent_context *)
tevent_common_loop_timer_delay: struct timeval (struct tevent_context *)
tevent_common_loop_wait: int (struct tevent_context *, const char *)
tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
tevent_context_init: struct tevent_context *(TALLOC_CTX *)
tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *)
tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...)
tevent_fd_get_flags: uint16_t (struct tevent_fd *)
tevent_fd_set_auto_close: void (struct tevent_fd *)
tevent_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
tevent_fd_set_flags: void (struct tevent_fd *, uint16_t)
tevent_loop_allow_nesting: void (struct tevent_context *)
tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *)
tevent_queue_add: bool (struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
tevent_queue_length: size_t (struct tevent_queue *)
tevent_queue_start: void (struct tevent_queue *)
tevent_queue_stop: void (struct tevent_queue *)
tevent_re_initialise: int (struct tevent_context *)
tevent_register_backend: bool (const char *, const struct tevent_ops *)
tevent_req_default_print: char *(struct tevent_req *, TALLOC_CTX *)
tevent_req_is_error: bool (struct tevent_req *, enum tevent_req_state *, uint64_t *)
tevent_req_is_in_progress: bool (struct tevent_req *)
tevent_req_poll: bool (struct tevent_req *, struct tevent_context *)
tevent_req_post: struct tevent_req *(struct tevent_req *, struct tevent_context *)
tevent_req_print: char *(TALLOC_CTX *, struct tevent_req *)
tevent_req_received: void (struct tevent_req *)
tevent_req_set_callback: void (struct tevent_req *, tevent_req_fn, void *)
tevent_req_set_cancel_fn: void (struct tevent_req *, tevent_req_cancel_fn)
tevent_req_set_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval)
tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn)
tevent_set_abort_fn: void (void (*)(const char *))
tevent_set_debug: int (struct tevent_context *, void (*)(void *, enum tevent_debug_level, const char *, va_list), void *)
tevent_set_debug_stderr: int (struct tevent_context *)
tevent_set_default_backend: void (const char *)
tevent_signal_support: bool (struct tevent_context *)
tevent_timeval_add: struct timeval (const struct timeval *, uint32_t, uint32_t)
tevent_timeval_compare: int (const struct timeval *, const struct timeval *)
tevent_timeval_current: struct timeval (void)
tevent_timeval_current_ofs: struct timeval (uint32_t, uint32_t)
tevent_timeval_is_zero: bool (const struct timeval *)
tevent_timeval_set: struct timeval (uint32_t, uint32_t)
tevent_timeval_until: struct timeval (const struct timeval *, const struct timeval *)
tevent_timeval_zero: struct timeval (void)
tevent_wakeup_recv: bool (struct tevent_req *)
tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval)

View File

@ -0,0 +1,75 @@
_tevent_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
_tevent_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
_tevent_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
_tevent_create_immediate: struct tevent_immediate *(TALLOC_CTX *, const char *)
_tevent_loop_once: int (struct tevent_context *, const char *)
_tevent_loop_until: int (struct tevent_context *, bool (*)(void *), void *, const char *)
_tevent_loop_wait: int (struct tevent_context *, const char *)
_tevent_queue_create: struct tevent_queue *(TALLOC_CTX *, const char *, const char *)
_tevent_req_callback_data: void *(struct tevent_req *)
_tevent_req_cancel: bool (struct tevent_req *, const char *)
_tevent_req_create: struct tevent_req *(TALLOC_CTX *, void *, size_t, const char *, const char *)
_tevent_req_data: void *(struct tevent_req *)
_tevent_req_done: void (struct tevent_req *, const char *)
_tevent_req_error: bool (struct tevent_req *, uint64_t, const char *)
_tevent_req_nomem: bool (const void *, struct tevent_req *, const char *)
_tevent_req_notify_callback: void (struct tevent_req *, const char *)
_tevent_req_oom: void (struct tevent_req *, const char *)
_tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
tevent_backend_list: const char **(TALLOC_CTX *)
tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *)
tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
tevent_common_check_signal: int (struct tevent_context *)
tevent_common_context_destructor: int (struct tevent_context *)
tevent_common_fd_destructor: int (struct tevent_fd *)
tevent_common_fd_get_flags: uint16_t (struct tevent_fd *)
tevent_common_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
tevent_common_fd_set_flags: void (struct tevent_fd *, uint16_t)
tevent_common_loop_immediate: bool (struct tevent_context *)
tevent_common_loop_timer_delay: struct timeval (struct tevent_context *)
tevent_common_loop_wait: int (struct tevent_context *, const char *)
tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
tevent_context_init: struct tevent_context *(TALLOC_CTX *)
tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *)
tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...)
tevent_fd_get_flags: uint16_t (struct tevent_fd *)
tevent_fd_set_auto_close: void (struct tevent_fd *)
tevent_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
tevent_fd_set_flags: void (struct tevent_fd *, uint16_t)
tevent_loop_allow_nesting: void (struct tevent_context *)
tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *)
tevent_queue_add: bool (struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
tevent_queue_length: size_t (struct tevent_queue *)
tevent_queue_start: void (struct tevent_queue *)
tevent_queue_stop: void (struct tevent_queue *)
tevent_re_initialise: int (struct tevent_context *)
tevent_register_backend: bool (const char *, const struct tevent_ops *)
tevent_req_default_print: char *(struct tevent_req *, TALLOC_CTX *)
tevent_req_defer_callback: void (struct tevent_req *, struct tevent_context *)
tevent_req_is_error: bool (struct tevent_req *, enum tevent_req_state *, uint64_t *)
tevent_req_is_in_progress: bool (struct tevent_req *)
tevent_req_poll: bool (struct tevent_req *, struct tevent_context *)
tevent_req_post: struct tevent_req *(struct tevent_req *, struct tevent_context *)
tevent_req_print: char *(TALLOC_CTX *, struct tevent_req *)
tevent_req_received: void (struct tevent_req *)
tevent_req_set_callback: void (struct tevent_req *, tevent_req_fn, void *)
tevent_req_set_cancel_fn: void (struct tevent_req *, tevent_req_cancel_fn)
tevent_req_set_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval)
tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn)
tevent_set_abort_fn: void (void (*)(const char *))
tevent_set_debug: int (struct tevent_context *, void (*)(void *, enum tevent_debug_level, const char *, va_list), void *)
tevent_set_debug_stderr: int (struct tevent_context *)
tevent_set_default_backend: void (const char *)
tevent_signal_support: bool (struct tevent_context *)
tevent_timeval_add: struct timeval (const struct timeval *, uint32_t, uint32_t)
tevent_timeval_compare: int (const struct timeval *, const struct timeval *)
tevent_timeval_current: struct timeval (void)
tevent_timeval_current_ofs: struct timeval (uint32_t, uint32_t)
tevent_timeval_is_zero: bool (const struct timeval *)
tevent_timeval_set: struct timeval (uint32_t, uint32_t)
tevent_timeval_until: struct timeval (const struct timeval *, const struct timeval *)
tevent_timeval_zero: struct timeval (void)
tevent_wakeup_recv: bool (struct tevent_req *)
tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval)

View File

@ -0,0 +1,78 @@
_tevent_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
_tevent_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
_tevent_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
_tevent_create_immediate: struct tevent_immediate *(TALLOC_CTX *, const char *)
_tevent_loop_once: int (struct tevent_context *, const char *)
_tevent_loop_until: int (struct tevent_context *, bool (*)(void *), void *, const char *)
_tevent_loop_wait: int (struct tevent_context *, const char *)
_tevent_queue_create: struct tevent_queue *(TALLOC_CTX *, const char *, const char *)
_tevent_req_callback_data: void *(struct tevent_req *)
_tevent_req_cancel: bool (struct tevent_req *, const char *)
_tevent_req_create: struct tevent_req *(TALLOC_CTX *, void *, size_t, const char *, const char *)
_tevent_req_data: void *(struct tevent_req *)
_tevent_req_done: void (struct tevent_req *, const char *)
_tevent_req_error: bool (struct tevent_req *, uint64_t, const char *)
_tevent_req_nomem: bool (const void *, struct tevent_req *, const char *)
_tevent_req_notify_callback: void (struct tevent_req *, const char *)
_tevent_req_oom: void (struct tevent_req *, const char *)
_tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
tevent_backend_list: const char **(TALLOC_CTX *)
tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *)
tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
tevent_common_check_signal: int (struct tevent_context *)
tevent_common_context_destructor: int (struct tevent_context *)
tevent_common_fd_destructor: int (struct tevent_fd *)
tevent_common_fd_get_flags: uint16_t (struct tevent_fd *)
tevent_common_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
tevent_common_fd_set_flags: void (struct tevent_fd *, uint16_t)
tevent_common_loop_immediate: bool (struct tevent_context *)
tevent_common_loop_timer_delay: struct timeval (struct tevent_context *)
tevent_common_loop_wait: int (struct tevent_context *, const char *)
tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
tevent_context_init: struct tevent_context *(TALLOC_CTX *)
tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *)
tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...)
tevent_fd_get_flags: uint16_t (struct tevent_fd *)
tevent_fd_set_auto_close: void (struct tevent_fd *)
tevent_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
tevent_fd_set_flags: void (struct tevent_fd *, uint16_t)
tevent_loop_allow_nesting: void (struct tevent_context *)
tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *)
tevent_queue_add: bool (struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
tevent_queue_add_entry: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
tevent_queue_add_optimize_empty: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
tevent_queue_length: size_t (struct tevent_queue *)
tevent_queue_running: bool (struct tevent_queue *)
tevent_queue_start: void (struct tevent_queue *)
tevent_queue_stop: void (struct tevent_queue *)
tevent_re_initialise: int (struct tevent_context *)
tevent_register_backend: bool (const char *, const struct tevent_ops *)
tevent_req_default_print: char *(struct tevent_req *, TALLOC_CTX *)
tevent_req_defer_callback: void (struct tevent_req *, struct tevent_context *)
tevent_req_is_error: bool (struct tevent_req *, enum tevent_req_state *, uint64_t *)
tevent_req_is_in_progress: bool (struct tevent_req *)
tevent_req_poll: bool (struct tevent_req *, struct tevent_context *)
tevent_req_post: struct tevent_req *(struct tevent_req *, struct tevent_context *)
tevent_req_print: char *(TALLOC_CTX *, struct tevent_req *)
tevent_req_received: void (struct tevent_req *)
tevent_req_set_callback: void (struct tevent_req *, tevent_req_fn, void *)
tevent_req_set_cancel_fn: void (struct tevent_req *, tevent_req_cancel_fn)
tevent_req_set_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval)
tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn)
tevent_set_abort_fn: void (void (*)(const char *))
tevent_set_debug: int (struct tevent_context *, void (*)(void *, enum tevent_debug_level, const char *, va_list), void *)
tevent_set_debug_stderr: int (struct tevent_context *)
tevent_set_default_backend: void (const char *)
tevent_signal_support: bool (struct tevent_context *)
tevent_timeval_add: struct timeval (const struct timeval *, uint32_t, uint32_t)
tevent_timeval_compare: int (const struct timeval *, const struct timeval *)
tevent_timeval_current: struct timeval (void)
tevent_timeval_current_ofs: struct timeval (uint32_t, uint32_t)
tevent_timeval_is_zero: bool (const struct timeval *)
tevent_timeval_set: struct timeval (uint32_t, uint32_t)
tevent_timeval_until: struct timeval (const struct timeval *, const struct timeval *)
tevent_timeval_zero: struct timeval (void)
tevent_wakeup_recv: bool (struct tevent_req *)
tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval)

View File

@ -0,0 +1,82 @@
_tevent_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
_tevent_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
_tevent_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
_tevent_create_immediate: struct tevent_immediate *(TALLOC_CTX *, const char *)
_tevent_loop_once: int (struct tevent_context *, const char *)
_tevent_loop_until: int (struct tevent_context *, bool (*)(void *), void *, const char *)
_tevent_loop_wait: int (struct tevent_context *, const char *)
_tevent_queue_create: struct tevent_queue *(TALLOC_CTX *, const char *, const char *)
_tevent_req_callback_data: void *(struct tevent_req *)
_tevent_req_cancel: bool (struct tevent_req *, const char *)
_tevent_req_create: struct tevent_req *(TALLOC_CTX *, void *, size_t, const char *, const char *)
_tevent_req_data: void *(struct tevent_req *)
_tevent_req_done: void (struct tevent_req *, const char *)
_tevent_req_error: bool (struct tevent_req *, uint64_t, const char *)
_tevent_req_nomem: bool (const void *, struct tevent_req *, const char *)
_tevent_req_notify_callback: void (struct tevent_req *, const char *)
_tevent_req_oom: void (struct tevent_req *, const char *)
_tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
tevent_backend_list: const char **(TALLOC_CTX *)
tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *)
tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
tevent_common_check_signal: int (struct tevent_context *)
tevent_common_context_destructor: int (struct tevent_context *)
tevent_common_fd_destructor: int (struct tevent_fd *)
tevent_common_fd_get_flags: uint16_t (struct tevent_fd *)
tevent_common_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
tevent_common_fd_set_flags: void (struct tevent_fd *, uint16_t)
tevent_common_loop_immediate: bool (struct tevent_context *)
tevent_common_loop_timer_delay: struct timeval (struct tevent_context *)
tevent_common_loop_wait: int (struct tevent_context *, const char *)
tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
tevent_context_init: struct tevent_context *(TALLOC_CTX *)
tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *)
tevent_context_init_ops: struct tevent_context *(TALLOC_CTX *, const struct tevent_ops *, void *)
tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...)
tevent_fd_get_flags: uint16_t (struct tevent_fd *)
tevent_fd_set_auto_close: void (struct tevent_fd *)
tevent_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
tevent_fd_set_flags: void (struct tevent_fd *, uint16_t)
tevent_get_trace_callback: void (struct tevent_context *, tevent_trace_callback_t *, void *)
tevent_loop_allow_nesting: void (struct tevent_context *)
tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *)
tevent_queue_add: bool (struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
tevent_queue_add_entry: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
tevent_queue_add_optimize_empty: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
tevent_queue_length: size_t (struct tevent_queue *)
tevent_queue_running: bool (struct tevent_queue *)
tevent_queue_start: void (struct tevent_queue *)
tevent_queue_stop: void (struct tevent_queue *)
tevent_re_initialise: int (struct tevent_context *)
tevent_register_backend: bool (const char *, const struct tevent_ops *)
tevent_req_default_print: char *(struct tevent_req *, TALLOC_CTX *)
tevent_req_defer_callback: void (struct tevent_req *, struct tevent_context *)
tevent_req_is_error: bool (struct tevent_req *, enum tevent_req_state *, uint64_t *)
tevent_req_is_in_progress: bool (struct tevent_req *)
tevent_req_poll: bool (struct tevent_req *, struct tevent_context *)
tevent_req_post: struct tevent_req *(struct tevent_req *, struct tevent_context *)
tevent_req_print: char *(TALLOC_CTX *, struct tevent_req *)
tevent_req_received: void (struct tevent_req *)
tevent_req_set_callback: void (struct tevent_req *, tevent_req_fn, void *)
tevent_req_set_cancel_fn: void (struct tevent_req *, tevent_req_cancel_fn)
tevent_req_set_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval)
tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn)
tevent_set_abort_fn: void (void (*)(const char *))
tevent_set_debug: int (struct tevent_context *, void (*)(void *, enum tevent_debug_level, const char *, va_list), void *)
tevent_set_debug_stderr: int (struct tevent_context *)
tevent_set_default_backend: void (const char *)
tevent_set_trace_callback: void (struct tevent_context *, tevent_trace_callback_t, void *)
tevent_signal_support: bool (struct tevent_context *)
tevent_timeval_add: struct timeval (const struct timeval *, uint32_t, uint32_t)
tevent_timeval_compare: int (const struct timeval *, const struct timeval *)
tevent_timeval_current: struct timeval (void)
tevent_timeval_current_ofs: struct timeval (uint32_t, uint32_t)
tevent_timeval_is_zero: bool (const struct timeval *)
tevent_timeval_set: struct timeval (uint32_t, uint32_t)
tevent_timeval_until: struct timeval (const struct timeval *, const struct timeval *)
tevent_timeval_zero: struct timeval (void)
tevent_trace_point_callback: void (struct tevent_context *, enum tevent_trace_point)
tevent_wakeup_recv: bool (struct tevent_req *)
tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval)

View File

@ -0,0 +1,83 @@
_tevent_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
_tevent_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
_tevent_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
_tevent_create_immediate: struct tevent_immediate *(TALLOC_CTX *, const char *)
_tevent_loop_once: int (struct tevent_context *, const char *)
_tevent_loop_until: int (struct tevent_context *, bool (*)(void *), void *, const char *)
_tevent_loop_wait: int (struct tevent_context *, const char *)
_tevent_queue_create: struct tevent_queue *(TALLOC_CTX *, const char *, const char *)
_tevent_req_callback_data: void *(struct tevent_req *)
_tevent_req_cancel: bool (struct tevent_req *, const char *)
_tevent_req_create: struct tevent_req *(TALLOC_CTX *, void *, size_t, const char *, const char *)
_tevent_req_data: void *(struct tevent_req *)
_tevent_req_done: void (struct tevent_req *, const char *)
_tevent_req_error: bool (struct tevent_req *, uint64_t, const char *)
_tevent_req_nomem: bool (const void *, struct tevent_req *, const char *)
_tevent_req_notify_callback: void (struct tevent_req *, const char *)
_tevent_req_oom: void (struct tevent_req *, const char *)
_tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
tevent_backend_list: const char **(TALLOC_CTX *)
tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *)
tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
tevent_common_add_timer_v2: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
tevent_common_check_signal: int (struct tevent_context *)
tevent_common_context_destructor: int (struct tevent_context *)
tevent_common_fd_destructor: int (struct tevent_fd *)
tevent_common_fd_get_flags: uint16_t (struct tevent_fd *)
tevent_common_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
tevent_common_fd_set_flags: void (struct tevent_fd *, uint16_t)
tevent_common_loop_immediate: bool (struct tevent_context *)
tevent_common_loop_timer_delay: struct timeval (struct tevent_context *)
tevent_common_loop_wait: int (struct tevent_context *, const char *)
tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
tevent_context_init: struct tevent_context *(TALLOC_CTX *)
tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *)
tevent_context_init_ops: struct tevent_context *(TALLOC_CTX *, const struct tevent_ops *, void *)
tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...)
tevent_fd_get_flags: uint16_t (struct tevent_fd *)
tevent_fd_set_auto_close: void (struct tevent_fd *)
tevent_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
tevent_fd_set_flags: void (struct tevent_fd *, uint16_t)
tevent_get_trace_callback: void (struct tevent_context *, tevent_trace_callback_t *, void *)
tevent_loop_allow_nesting: void (struct tevent_context *)
tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *)
tevent_queue_add: bool (struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
tevent_queue_add_entry: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
tevent_queue_add_optimize_empty: struct tevent_queue_entry *(struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
tevent_queue_length: size_t (struct tevent_queue *)
tevent_queue_running: bool (struct tevent_queue *)
tevent_queue_start: void (struct tevent_queue *)
tevent_queue_stop: void (struct tevent_queue *)
tevent_re_initialise: int (struct tevent_context *)
tevent_register_backend: bool (const char *, const struct tevent_ops *)
tevent_req_default_print: char *(struct tevent_req *, TALLOC_CTX *)
tevent_req_defer_callback: void (struct tevent_req *, struct tevent_context *)
tevent_req_is_error: bool (struct tevent_req *, enum tevent_req_state *, uint64_t *)
tevent_req_is_in_progress: bool (struct tevent_req *)
tevent_req_poll: bool (struct tevent_req *, struct tevent_context *)
tevent_req_post: struct tevent_req *(struct tevent_req *, struct tevent_context *)
tevent_req_print: char *(TALLOC_CTX *, struct tevent_req *)
tevent_req_received: void (struct tevent_req *)
tevent_req_set_callback: void (struct tevent_req *, tevent_req_fn, void *)
tevent_req_set_cancel_fn: void (struct tevent_req *, tevent_req_cancel_fn)
tevent_req_set_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval)
tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn)
tevent_set_abort_fn: void (void (*)(const char *))
tevent_set_debug: int (struct tevent_context *, void (*)(void *, enum tevent_debug_level, const char *, va_list), void *)
tevent_set_debug_stderr: int (struct tevent_context *)
tevent_set_default_backend: void (const char *)
tevent_set_trace_callback: void (struct tevent_context *, tevent_trace_callback_t, void *)
tevent_signal_support: bool (struct tevent_context *)
tevent_timeval_add: struct timeval (const struct timeval *, uint32_t, uint32_t)
tevent_timeval_compare: int (const struct timeval *, const struct timeval *)
tevent_timeval_current: struct timeval (void)
tevent_timeval_current_ofs: struct timeval (uint32_t, uint32_t)
tevent_timeval_is_zero: bool (const struct timeval *)
tevent_timeval_set: struct timeval (uint32_t, uint32_t)
tevent_timeval_until: struct timeval (const struct timeval *, const struct timeval *)
tevent_timeval_zero: struct timeval (void)
tevent_trace_point_callback: void (struct tevent_context *, enum tevent_trace_point)
tevent_wakeup_recv: bool (struct tevent_req *)
tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval)

View File

@ -0,0 +1,73 @@
_tevent_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
_tevent_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
_tevent_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
_tevent_create_immediate: struct tevent_immediate *(TALLOC_CTX *, const char *)
_tevent_loop_once: int (struct tevent_context *, const char *)
_tevent_loop_until: int (struct tevent_context *, bool (*)(void *), void *, const char *)
_tevent_loop_wait: int (struct tevent_context *, const char *)
_tevent_queue_create: struct tevent_queue *(TALLOC_CTX *, const char *, const char *)
_tevent_req_callback_data: void *(struct tevent_req *)
_tevent_req_cancel: bool (struct tevent_req *, const char *)
_tevent_req_create: struct tevent_req *(TALLOC_CTX *, void *, size_t, const char *, const char *)
_tevent_req_data: void *(struct tevent_req *)
_tevent_req_done: void (struct tevent_req *, const char *)
_tevent_req_error: bool (struct tevent_req *, uint64_t, const char *)
_tevent_req_nomem: bool (const void *, struct tevent_req *, const char *)
_tevent_req_notify_callback: void (struct tevent_req *, const char *)
_tevent_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
tevent_backend_list: const char **(TALLOC_CTX *)
tevent_cleanup_pending_signal_handlers: void (struct tevent_signal *)
tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *, int, uint16_t, tevent_fd_handler_t, void *, const char *, const char *)
tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
tevent_common_check_signal: int (struct tevent_context *)
tevent_common_context_destructor: int (struct tevent_context *)
tevent_common_fd_destructor: int (struct tevent_fd *)
tevent_common_fd_get_flags: uint16_t (struct tevent_fd *)
tevent_common_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
tevent_common_fd_set_flags: void (struct tevent_fd *, uint16_t)
tevent_common_loop_immediate: bool (struct tevent_context *)
tevent_common_loop_timer_delay: struct timeval (struct tevent_context *)
tevent_common_loop_wait: int (struct tevent_context *, const char *)
tevent_common_schedule_immediate: void (struct tevent_immediate *, struct tevent_context *, tevent_immediate_handler_t, void *, const char *, const char *)
tevent_context_init: struct tevent_context *(TALLOC_CTX *)
tevent_context_init_byname: struct tevent_context *(TALLOC_CTX *, const char *)
tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...)
tevent_fd_get_flags: uint16_t (struct tevent_fd *)
tevent_fd_set_auto_close: void (struct tevent_fd *)
tevent_fd_set_close_fn: void (struct tevent_fd *, tevent_fd_close_fn_t)
tevent_fd_set_flags: void (struct tevent_fd *, uint16_t)
tevent_loop_allow_nesting: void (struct tevent_context *)
tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *)
tevent_queue_add: bool (struct tevent_queue *, struct tevent_context *, struct tevent_req *, tevent_queue_trigger_fn_t, void *)
tevent_queue_length: size_t (struct tevent_queue *)
tevent_queue_start: void (struct tevent_queue *)
tevent_queue_stop: void (struct tevent_queue *)
tevent_re_initialise: int (struct tevent_context *)
tevent_register_backend: bool (const char *, const struct tevent_ops *)
tevent_req_default_print: char *(struct tevent_req *, TALLOC_CTX *)
tevent_req_is_error: bool (struct tevent_req *, enum tevent_req_state *, uint64_t *)
tevent_req_is_in_progress: bool (struct tevent_req *)
tevent_req_poll: bool (struct tevent_req *, struct tevent_context *)
tevent_req_post: struct tevent_req *(struct tevent_req *, struct tevent_context *)
tevent_req_print: char *(TALLOC_CTX *, struct tevent_req *)
tevent_req_received: void (struct tevent_req *)
tevent_req_set_callback: void (struct tevent_req *, tevent_req_fn, void *)
tevent_req_set_cancel_fn: void (struct tevent_req *, tevent_req_cancel_fn)
tevent_req_set_endtime: bool (struct tevent_req *, struct tevent_context *, struct timeval)
tevent_req_set_print_fn: void (struct tevent_req *, tevent_req_print_fn)
tevent_set_abort_fn: void (void (*)(const char *))
tevent_set_debug: int (struct tevent_context *, void (*)(void *, enum tevent_debug_level, const char *, va_list), void *)
tevent_set_debug_stderr: int (struct tevent_context *)
tevent_set_default_backend: void (const char *)
tevent_signal_support: bool (struct tevent_context *)
tevent_timeval_add: struct timeval (const struct timeval *, uint32_t, uint32_t)
tevent_timeval_compare: int (const struct timeval *, const struct timeval *)
tevent_timeval_current: struct timeval (void)
tevent_timeval_current_ofs: struct timeval (uint32_t, uint32_t)
tevent_timeval_is_zero: bool (const struct timeval *)
tevent_timeval_set: struct timeval (uint32_t, uint32_t)
tevent_timeval_until: struct timeval (const struct timeval *, const struct timeval *)
tevent_timeval_zero: struct timeval (void)
tevent_wakeup_recv: bool (struct tevent_req *)
tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval)

View File

@ -0,0 +1,62 @@
#!/usr/bin/python
#
# Python integration for tevent - tests
#
# Copyright (C) Jelmer Vernooij 2010
#
# ** NOTE! The following LGPL license applies to the tevent
# ** library. This does NOT imply that all of Samba is released
# ** under the LGPL
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, see <http://www.gnu.org/licenses/>.
import signal
import _tevent
from unittest import TestCase
class BackendListTests(TestCase):
def test_backend_list(self):
self.assertTrue(isinstance(_tevent.backend_list(), list))
class CreateContextTests(TestCase):
def test_by_name(self):
ctx = _tevent.Context(_tevent.backend_list()[0])
self.assertTrue(ctx is not None)
def test_no_name(self):
ctx = _tevent.Context()
self.assertTrue(ctx is not None)
class ContextTests(TestCase):
def setUp(self):
super(ContextTests, self).setUp()
self.ctx = _tevent.Context()
def test_signal_support(self):
self.assertTrue(type(self.ctx.signal_support) is bool)
def test_reinitialise(self):
self.ctx.reinitialise()
def test_loop_wait(self):
self.ctx.loop_wait()
def test_add_signal(self):
sig = self.ctx.add_signal(signal.SIGINT, 0, lambda callback: None)
self.assertTrue(isinstance(sig, _tevent.Signal))

View File

@ -627,10 +627,7 @@ EXCLUDE_SYMLINKS = NO
# against the file with absolute path, so to exclude all test directories
# for example use the pattern */test/*
EXCLUDE_PATTERNS = */.git/* \
*/.svn/* \
*/cmake/* \
*/build/*
EXCLUDE_PATTERNS = */.git/*
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the

766
ctdb/lib/tevent/pytevent.c Normal file
View File

@ -0,0 +1,766 @@
/*
Unix SMB/CIFS implementation.
Python bindings for tevent
Copyright (C) Jelmer Vernooij 2010
** NOTE! The following LGPL license applies to the tevent
** library. This does NOT imply that all of Samba is released
** under the LGPL
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <Python.h>
#include <tevent.h>
void init_tevent(void);
typedef struct {
PyObject_HEAD
struct tevent_context *ev;
} TeventContext_Object;
typedef struct {
PyObject_HEAD
struct tevent_queue *queue;
} TeventQueue_Object;
typedef struct {
PyObject_HEAD
struct tevent_req *req;
} TeventReq_Object;
typedef struct {
PyObject_HEAD
struct tevent_signal *signal;
} TeventSignal_Object;
typedef struct {
PyObject_HEAD
struct tevent_timer *timer;
} TeventTimer_Object;
typedef struct {
PyObject_HEAD
struct tevent_fd *fd;
} TeventFd_Object;
staticforward PyTypeObject TeventContext_Type;
staticforward PyTypeObject TeventReq_Type;
staticforward PyTypeObject TeventQueue_Type;
staticforward PyTypeObject TeventSignal_Type;
staticforward PyTypeObject TeventTimer_Type;
staticforward PyTypeObject TeventFd_Type;
static int py_context_init(struct tevent_context *ev)
{
/* FIXME */
return 0;
}
static struct tevent_fd *py_add_fd(struct tevent_context *ev,
TALLOC_CTX *mem_ctx,
int fd, uint16_t flags,
tevent_fd_handler_t handler,
void *private_data,
const char *handler_name,
const char *location)
{
/* FIXME */
return NULL;
}
static void py_set_fd_close_fn(struct tevent_fd *fde,
tevent_fd_close_fn_t close_fn)
{
/* FIXME */
}
static uint16_t py_get_fd_flags(struct tevent_fd *fde)
{
/* FIXME */
return 0;
}
static void py_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
{
/* FIXME */
}
/* timed_event functions */
static struct tevent_timer *py_add_timer(struct tevent_context *ev,
TALLOC_CTX *mem_ctx,
struct timeval next_event,
tevent_timer_handler_t handler,
void *private_data,
const char *handler_name,
const char *location)
{
/* FIXME */
return NULL;
}
/* immediate event functions */
static void py_schedule_immediate(struct tevent_immediate *im,
struct tevent_context *ev,
tevent_immediate_handler_t handler,
void *private_data,
const char *handler_name,
const char *location)
{
/* FIXME */
}
/* signal functions */
static struct tevent_signal *py_add_signal(struct tevent_context *ev,
TALLOC_CTX *mem_ctx,
int signum, int sa_flags,
tevent_signal_handler_t handler,
void *private_data,
const char *handler_name,
const char *location)
{
/* FIXME */
return NULL;
}
/* loop functions */
static int py_loop_once(struct tevent_context *ev, const char *location)
{
/* FIXME */
return 0;
}
static int py_loop_wait(struct tevent_context *ev, const char *location)
{
/* FIXME */
return 0;
}
const static struct tevent_ops py_tevent_ops = {
.context_init = py_context_init,
.add_fd = py_add_fd,
.set_fd_close_fn = py_set_fd_close_fn,
.get_fd_flags = py_get_fd_flags,
.set_fd_flags = py_set_fd_flags,
.add_timer = py_add_timer,
.schedule_immediate = py_schedule_immediate,
.add_signal = py_add_signal,
.loop_wait = py_loop_wait,
.loop_once = py_loop_once,
};
static PyObject *py_register_backend(PyObject *self, PyObject *args)
{
PyObject *name, *py_backend;
if (!PyArg_ParseTuple(args, "O", &py_backend))
return NULL;
name = PyObject_GetAttrString(py_backend, "name");
if (name == NULL) {
PyErr_SetNone(PyExc_AttributeError);
return NULL;
}
if (!PyString_Check(name)) {
PyErr_SetNone(PyExc_TypeError);
return NULL;
}
if (!tevent_register_backend(PyString_AsString(name), &py_tevent_ops)) { /* FIXME: What to do with backend */
PyErr_SetNone(PyExc_RuntimeError);
return NULL;
}
Py_RETURN_NONE;
}
static PyObject *py_tevent_context_reinitialise(TeventContext_Object *self)
{
int ret = tevent_re_initialise(self->ev);
if (ret != 0) {
PyErr_SetNone(PyExc_RuntimeError);
return NULL;
}
Py_RETURN_NONE;
}
static PyObject *py_tevent_queue_stop(TeventQueue_Object *self)
{
tevent_queue_stop(self->queue);
Py_RETURN_NONE;
}
static PyObject *py_tevent_queue_start(TeventQueue_Object *self)
{
tevent_queue_start(self->queue);
Py_RETURN_NONE;
}
static void py_queue_trigger(struct tevent_req *req, void *private_data)
{
PyObject *callback = private_data, *ret;
ret = PyObject_CallFunction(callback, "");
Py_XDECREF(ret);
}
static PyObject *py_tevent_queue_add(TeventQueue_Object *self, PyObject *args)
{
TeventContext_Object *py_ev;
TeventReq_Object *py_req;
PyObject *trigger;
bool ret;
if (!PyArg_ParseTuple(args, "O!O!O",
&TeventContext_Type, &py_ev,
&TeventReq_Type, &py_req,
&trigger))
return NULL;
Py_INCREF(trigger);
ret = tevent_queue_add(self->queue, py_ev->ev, py_req->req,
py_queue_trigger, trigger);
if (!ret) {
PyErr_SetString(PyExc_RuntimeError, "queue add failed");
Py_DECREF(trigger);
return NULL;
}
Py_RETURN_NONE;
}
static PyMethodDef py_tevent_queue_methods[] = {
{ "stop", (PyCFunction)py_tevent_queue_stop, METH_NOARGS,
"S.stop()" },
{ "start", (PyCFunction)py_tevent_queue_start, METH_NOARGS,
"S.start()" },
{ "add", (PyCFunction)py_tevent_queue_add, METH_VARARGS,
"S.add(ctx, req, trigger, baton)" },
{ NULL },
};
static PyObject *py_tevent_context_wakeup_send(PyObject *self, PyObject *args)
{
/* FIXME */
Py_RETURN_NONE;
}
static PyObject *py_tevent_context_loop_wait(TeventContext_Object *self)
{
if (tevent_loop_wait(self->ev) != 0) {
PyErr_SetNone(PyExc_RuntimeError);
return NULL;
}
Py_RETURN_NONE;
}
static PyObject *py_tevent_context_loop_once(TeventContext_Object *self)
{
if (tevent_loop_once(self->ev) != 0) {
PyErr_SetNone(PyExc_RuntimeError);
return NULL;
}
Py_RETURN_NONE;
}
#ifdef TEVENT_DEPRECATED
static bool py_tevent_finished(PyObject *callback)
{
PyObject *py_ret;
bool ret;
py_ret = PyObject_CallFunction(callback, "");
if (py_ret == NULL)
return true;
ret = PyObject_IsTrue(py_ret);
Py_DECREF(py_ret);
return ret;
}
static PyObject *py_tevent_context_loop_until(TeventContext_Object *self, PyObject *args)
{
PyObject *callback;
if (!PyArg_ParseTuple(args, "O", &callback))
return NULL;
if (tevent_loop_until(self->ev, py_tevent_finished, callback) != 0) {
PyErr_SetNone(PyExc_RuntimeError);
return NULL;
}
if (PyErr_Occurred())
return NULL;
Py_RETURN_NONE;
}
#endif
static void py_tevent_signal_handler(struct tevent_context *ev,
struct tevent_signal *se,
int signum,
int count,
void *siginfo,
void *private_data)
{
PyObject *callback = (PyObject *)private_data, *ret;
ret = PyObject_CallFunction(callback, "ii", signum, count);
Py_XDECREF(ret);
}
static void py_tevent_signal_dealloc(TeventSignal_Object *self)
{
talloc_free(self->signal);
PyObject_Del(self);
}
static PyTypeObject TeventSignal_Type = {
.tp_name = "tevent.Signal",
.tp_basicsize = sizeof(TeventSignal_Object),
.tp_dealloc = (destructor)py_tevent_signal_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT,
};
static PyObject *py_tevent_context_add_signal(TeventContext_Object *self, PyObject *args)
{
int signum, sa_flags;
PyObject *handler;
struct tevent_signal *sig;
TeventSignal_Object *ret;
if (!PyArg_ParseTuple(args, "iiO", &signum, &sa_flags, &handler))
return NULL;
Py_INCREF(handler);
sig = tevent_add_signal(self->ev, NULL, signum, sa_flags,
py_tevent_signal_handler, handler);
ret = PyObject_New(TeventSignal_Object, &TeventSignal_Type);
if (ret == NULL) {
PyErr_NoMemory();
talloc_free(sig);
return NULL;
}
ret->signal = sig;
return (PyObject *)ret;
}
static void py_timer_handler(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval current_time,
void *private_data)
{
PyObject *callback = private_data, *ret;
ret = PyObject_CallFunction(callback, "l", te);
Py_XDECREF(ret);
}
static PyObject *py_tevent_context_add_timer(TeventContext_Object *self, PyObject *args)
{
TeventTimer_Object *ret;
struct timeval next_event;
struct tevent_timer *timer;
PyObject *handler;
if (!PyArg_ParseTuple(args, "lO", &next_event, &handler))
return NULL;
timer = tevent_add_timer(self->ev, NULL, next_event, py_timer_handler,
handler);
if (timer == NULL) {
PyErr_SetNone(PyExc_RuntimeError);
return NULL;
}
ret = PyObject_New(TeventTimer_Object, &TeventTimer_Type);
if (ret == NULL) {
PyErr_NoMemory();
talloc_free(timer);
return NULL;
}
ret->timer = timer;
return (PyObject *)ret;
}
static void py_fd_handler(struct tevent_context *ev,
struct tevent_fd *fde,
uint16_t flags,
void *private_data)
{
PyObject *callback = private_data, *ret;
ret = PyObject_CallFunction(callback, "i", flags);
Py_XDECREF(ret);
}
static PyObject *py_tevent_context_add_fd(TeventContext_Object *self, PyObject *args)
{
int fd, flags;
PyObject *handler;
struct tevent_fd *tfd;
TeventFd_Object *ret;
if (!PyArg_ParseTuple(args, "iiO", &fd, &flags, &handler))
return NULL;
tfd = tevent_add_fd(self->ev, NULL, fd, flags, py_fd_handler, handler);
if (tfd == NULL) {
PyErr_SetNone(PyExc_RuntimeError);
return NULL;
}
ret = PyObject_New(TeventFd_Object, &TeventFd_Type);
if (ret == NULL) {
talloc_free(tfd);
return NULL;
}
ret->fd = tfd;
return (PyObject *)ret;
}
#ifdef TEVENT_DEPRECATED
static PyObject *py_tevent_context_set_allow_nesting(TeventContext_Object *self)
{
tevent_loop_allow_nesting(self->ev);
Py_RETURN_NONE;
}
#endif
static PyMethodDef py_tevent_context_methods[] = {
{ "reinitialise", (PyCFunction)py_tevent_context_reinitialise, METH_NOARGS,
"S.reinitialise()" },
{ "wakeup_send", (PyCFunction)py_tevent_context_wakeup_send,
METH_VARARGS, "S.wakeup_send(wakeup_time) -> req" },
{ "loop_wait", (PyCFunction)py_tevent_context_loop_wait,
METH_NOARGS, "S.loop_wait()" },
{ "loop_once", (PyCFunction)py_tevent_context_loop_once,
METH_NOARGS, "S.loop_once()" },
#ifdef TEVENT_DEPRECATED
{ "loop_until", (PyCFunction)py_tevent_context_loop_until,
METH_VARARGS, "S.loop_until(callback)" },
#endif
{ "add_signal", (PyCFunction)py_tevent_context_add_signal,
METH_VARARGS, "S.add_signal(signum, sa_flags, handler) -> signal" },
{ "add_timer", (PyCFunction)py_tevent_context_add_timer,
METH_VARARGS, "S.add_timer(next_event, handler) -> timer" },
{ "add_fd", (PyCFunction)py_tevent_context_add_fd,
METH_VARARGS, "S.add_fd(fd, flags, handler) -> fd" },
#ifdef TEVENT_DEPRECATED
{ "allow_nesting", (PyCFunction)py_tevent_context_set_allow_nesting,
METH_NOARGS, "Whether to allow nested tevent loops." },
#endif
{ NULL },
};
static PyObject *py_tevent_req_wakeup_recv(PyObject *self)
{
/* FIXME */
Py_RETURN_NONE;
}
static PyObject *py_tevent_req_received(PyObject *self)
{
/* FIXME */
Py_RETURN_NONE;
}
static PyObject *py_tevent_req_is_error(PyObject *self)
{
/* FIXME */
Py_RETURN_NONE;
}
static PyObject *py_tevent_req_poll(PyObject *self)
{
/* FIXME */
Py_RETURN_NONE;
}
static PyObject *py_tevent_req_is_in_progress(PyObject *self)
{
/* FIXME */
Py_RETURN_NONE;
}
static PyGetSetDef py_tevent_req_getsetters[] = {
{ "in_progress", (getter)py_tevent_req_is_in_progress, NULL,
"Whether the request is in progress" },
{ NULL }
};
static PyObject *py_tevent_req_post(PyObject *self, PyObject *args)
{
/* FIXME */
Py_RETURN_NONE;
}
static PyObject *py_tevent_req_set_error(PyObject *self, PyObject *args)
{
/* FIXME */
Py_RETURN_NONE;
}
static PyObject *py_tevent_req_done(PyObject *self)
{
/* FIXME */
Py_RETURN_NONE;
}
static PyObject *py_tevent_req_notify_callback(PyObject *self)
{
/* FIXME */
Py_RETURN_NONE;
}
static PyObject *py_tevent_req_set_endtime(PyObject *self, PyObject *args)
{
/* FIXME */
Py_RETURN_NONE;
}
static PyObject *py_tevent_req_cancel(TeventReq_Object *self)
{
if (!tevent_req_cancel(self->req)) {
PyErr_SetNone(PyExc_RuntimeError);
return NULL;
}
Py_RETURN_NONE;
}
static PyMethodDef py_tevent_req_methods[] = {
{ "wakeup_recv", (PyCFunction)py_tevent_req_wakeup_recv, METH_NOARGS,
"Wakeup received" },
{ "received", (PyCFunction)py_tevent_req_received, METH_NOARGS,
"Receive finished" },
{ "is_error", (PyCFunction)py_tevent_req_is_error, METH_NOARGS,
"is_error() -> (error, state)" },
{ "poll", (PyCFunction)py_tevent_req_poll, METH_VARARGS,
"poll(ctx)" },
{ "post", (PyCFunction)py_tevent_req_post, METH_VARARGS,
"post(ctx) -> req" },
{ "set_error", (PyCFunction)py_tevent_req_set_error, METH_VARARGS,
"set_error(error)" },
{ "done", (PyCFunction)py_tevent_req_done, METH_NOARGS,
"done()" },
{ "notify_callback", (PyCFunction)py_tevent_req_notify_callback,
METH_NOARGS, "notify_callback()" },
{ "set_endtime", (PyCFunction)py_tevent_req_set_endtime,
METH_VARARGS, "set_endtime(ctx, endtime)" },
{ "cancel", (PyCFunction)py_tevent_req_cancel,
METH_NOARGS, "cancel()" },
{ NULL }
};
static void py_tevent_req_dealloc(TeventReq_Object *self)
{
talloc_free(self->req);
PyObject_DEL(self);
}
static PyTypeObject TeventReq_Type = {
.tp_name = "tevent.Request",
.tp_basicsize = sizeof(TeventReq_Object),
.tp_methods = py_tevent_req_methods,
.tp_dealloc = (destructor)py_tevent_req_dealloc,
.tp_getset = py_tevent_req_getsetters,
/* FIXME: .tp_new = py_tevent_req_new, */
};
static PyObject *py_tevent_queue_get_length(TeventQueue_Object *self)
{
return PyInt_FromLong(tevent_queue_length(self->queue));
}
static PyGetSetDef py_tevent_queue_getsetters[] = {
{ "length", (getter)py_tevent_queue_get_length,
NULL, "The number of elements in the queue." },
{ NULL },
};
static void py_tevent_queue_dealloc(TeventQueue_Object *self)
{
talloc_free(self->queue);
PyObject_Del(self);
}
static PyTypeObject TeventQueue_Type = {
.tp_name = "tevent.Queue",
.tp_basicsize = sizeof(TeventQueue_Object),
.tp_dealloc = (destructor)py_tevent_queue_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_getset = py_tevent_queue_getsetters,
.tp_methods = py_tevent_queue_methods,
};
static PyObject *py_tevent_context_signal_support(PyObject *_self)
{
TeventContext_Object *self = (TeventContext_Object *)_self;
return PyBool_FromLong(tevent_signal_support(self->ev));
}
static PyGetSetDef py_tevent_context_getsetters[] = {
{ "signal_support", (getter)py_tevent_context_signal_support,
NULL, "if this platform and tevent context support signal handling" },
{ NULL }
};
static void py_tevent_context_dealloc(TeventContext_Object *self)
{
talloc_free(self->ev);
PyObject_Del(self);
}
static PyObject *py_tevent_context_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
const char * const kwnames[] = { "name", NULL };
char *name = NULL;
struct tevent_context *ev;
TeventContext_Object *ret;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwnames, &name))
return NULL;
if (name == NULL) {
ev = tevent_context_init(NULL);
} else {
ev = tevent_context_init_byname(NULL, name);
}
if (ev == NULL) {
PyErr_SetNone(PyExc_RuntimeError);
return NULL;
}
ret = PyObject_New(TeventContext_Object, type);
if (ret == NULL) {
PyErr_NoMemory();
talloc_free(ev);
return NULL;
}
ret->ev = ev;
return (PyObject *)ret;
}
static PyTypeObject TeventContext_Type = {
.tp_name = "tevent.Context",
.tp_new = py_tevent_context_new,
.tp_basicsize = sizeof(TeventContext_Object),
.tp_dealloc = (destructor)py_tevent_context_dealloc,
.tp_methods = py_tevent_context_methods,
.tp_getset = py_tevent_context_getsetters,
.tp_flags = Py_TPFLAGS_DEFAULT,
};
static PyObject *py_set_default_backend(PyObject *self, PyObject *args)
{
char *backend_name;
if (!PyArg_ParseTuple(args, "s", &backend_name))
return NULL;
tevent_set_default_backend(backend_name);
Py_RETURN_NONE;
}
static PyObject *py_backend_list(PyObject *self)
{
PyObject *ret;
int i;
const char **backends;
ret = PyList_New(0);
if (ret == NULL) {
return NULL;
}
backends = tevent_backend_list(NULL);
if (backends == NULL) {
PyErr_SetNone(PyExc_RuntimeError);
Py_DECREF(ret);
return NULL;
}
for (i = 0; backends[i]; i++) {
PyList_Append(ret, PyString_FromString(backends[i]));
}
talloc_free(backends);
return ret;
}
static PyMethodDef tevent_methods[] = {
{ "register_backend", (PyCFunction)py_register_backend, METH_VARARGS,
"register_backend(backend)" },
{ "set_default_backend", (PyCFunction)py_set_default_backend,
METH_VARARGS, "set_default_backend(backend)" },
{ "backend_list", (PyCFunction)py_backend_list,
METH_NOARGS, "backend_list() -> list" },
{ NULL },
};
void init_tevent(void)
{
PyObject *m;
if (PyType_Ready(&TeventContext_Type) < 0)
return;
if (PyType_Ready(&TeventQueue_Type) < 0)
return;
if (PyType_Ready(&TeventReq_Type) < 0)
return;
if (PyType_Ready(&TeventSignal_Type) < 0)
return;
if (PyType_Ready(&TeventTimer_Type) < 0)
return;
if (PyType_Ready(&TeventFd_Type) < 0)
return;
m = Py_InitModule3("_tevent", tevent_methods, "Tevent integration for twisted.");
if (m == NULL)
return;
Py_INCREF(&TeventContext_Type);
PyModule_AddObject(m, "Context", (PyObject *)&TeventContext_Type);
Py_INCREF(&TeventQueue_Type);
PyModule_AddObject(m, "Queue", (PyObject *)&TeventQueue_Type);
Py_INCREF(&TeventReq_Type);
PyModule_AddObject(m, "Request", (PyObject *)&TeventReq_Type);
Py_INCREF(&TeventSignal_Type);
PyModule_AddObject(m, "Signal", (PyObject *)&TeventSignal_Type);
Py_INCREF(&TeventTimer_Type);
PyModule_AddObject(m, "Timer", (PyObject *)&TeventTimer_Type);
Py_INCREF(&TeventFd_Type);
PyModule_AddObject(m, "Fd", (PyObject *)&TeventFd_Type);
PyModule_AddObject(m, "__version__", PyString_FromString(PACKAGE_VERSION));
}

View File

@ -0,0 +1,48 @@
#!/bin/bash
if [ "$1" = "" ]; then
echo "Please provide version string, eg: 1.2.0"
exit 1
fi
if [ ! -d "lib/tevent" ]; then
echo "Run this script from the samba base directory."
exit 1
fi
git clean -f -x -d lib/tevent
git clean -f -x -d lib/replace
curbranch=`git-branch |grep "^*" | tr -d "* "`
version=$1
strver=`echo ${version} | tr "." "-"`
# Checkout the release tag
git branch -f tevent-release-script-${strver} tevent-${strver}
if [ ! "$?" = "0" ]; then
echo "Unable to checkout tevent-${strver} release"
exit 1
fi
git checkout tevent-release-script-${strver}
# Test configure agrees with us
confver=`grep "^AC_INIT" lib/tevent/configure.ac | tr -d "AC_INIT(tevent, " | tr -d ")"`
if [ ! "$confver" = "$version" ]; then
echo "Wrong version, requested release for ${version}, found ${confver}"
exit 1
fi
# Now build tarball
cp -a lib/tevent tevent-${version}
cp -a lib/replace tevent-${version}/libreplace
pushd tevent-${version}
./autogen.sh
popd
tar cvzf tevent-${version}.tar.gz tevent-${version}
rm -fr tevent-${version}
#Clean up
git checkout $curbranch
git branch -d tevent-release-script-${strver}

View File

@ -1,9 +1,10 @@
/*
/*
Unix SMB/CIFS implementation.
testing of the events subsystem
Copyright (C) Stefan Metzmacher 2006-2009
Copyright (C) Jeremy Allison 2013
** NOTE! The following LGPL license applies to the tevent
** library. This does NOT imply that all of Samba is released
@ -24,13 +25,19 @@
*/
#include "includes.h"
#include "lib/events/events.h"
#include "lib/tevent/tevent.h"
#include "system/filesys.h"
#include "system/select.h"
#include "system/network.h"
#include "torture/torture.h"
#ifdef HAVE_PTHREAD
#include <pthread.h>
#include <assert.h>
#endif
static int fde_count;
static void fde_handler(struct tevent_context *ev_ctx, struct tevent_fd *f,
static void fde_handler_read(struct tevent_context *ev_ctx, struct tevent_fd *f,
uint16_t flags, void *private_data)
{
int *fd = (int *)private_data;
@ -39,11 +46,38 @@ static void fde_handler(struct tevent_context *ev_ctx, struct tevent_fd *f,
kill(getpid(), SIGUSR1);
#endif
kill(getpid(), SIGALRM);
read(fd[0], &c, 1);
write(fd[1], &c, 1);
fde_count++;
}
static void fde_handler_write(struct tevent_context *ev_ctx, struct tevent_fd *f,
uint16_t flags, void *private_data)
{
int *fd = (int *)private_data;
char c = 0;
write(fd[1], &c, 1);
}
/* These should never fire... */
static void fde_handler_read_1(struct tevent_context *ev_ctx, struct tevent_fd *f,
uint16_t flags, void *private_data)
{
struct torture_context *test = (struct torture_context *)private_data;
torture_comment(test, "fde_handler_read_1 should never fire !\n");
abort();
}
/* These should never fire... */
static void fde_handler_write_1(struct tevent_context *ev_ctx, struct tevent_fd *f,
uint16_t flags, void *private_data)
{
struct torture_context *test = (struct torture_context *)private_data;
torture_comment(test, "fde_handler_write_1 should never fire !\n");
abort();
}
static void finished_handler(struct tevent_context *ev_ctx, struct tevent_timer *te,
struct timeval tval, void *private_data)
{
@ -65,17 +99,21 @@ static bool test_event_context(struct torture_context *test,
int fd[2] = { -1, -1 };
const char *backend = (const char *)test_data;
int alarm_count=0, info_count=0;
struct tevent_fd *fde;
struct tevent_fd *fde_read;
struct tevent_fd *fde_read_1;
struct tevent_fd *fde_write;
struct tevent_fd *fde_write_1;
#ifdef SA_RESTART
struct tevent_signal *se1 = NULL;
#endif
#ifdef SA_RESETHAND
struct tevent_signal *se2 = NULL;
#endif
#ifdef SA_SIGINFO
struct tevent_signal *se3 = NULL;
#endif
int finished=0;
struct timeval t;
char c = 0;
ev_ctx = tevent_context_init_byname(test, backend);
if (ev_ctx == NULL) {
@ -83,7 +121,8 @@ static bool test_event_context(struct torture_context *test,
return true;
}
torture_comment(test, "Testing event backend '%s'\n", backend);
torture_comment(test, "backend '%s' - %s\n",
backend, __FUNCTION__);
/* reset globals */
fde_count = 0;
@ -91,25 +130,35 @@ static bool test_event_context(struct torture_context *test,
/* create a pipe */
pipe(fd);
fde = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_READ,
fde_handler, fd);
tevent_fd_set_auto_close(fde);
fde_read = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_READ,
fde_handler_read, fd);
fde_write_1 = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_WRITE,
fde_handler_write_1, test);
fde_write = tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_WRITE,
fde_handler_write, fd);
fde_read_1 = tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_READ,
fde_handler_read_1, test);
tevent_fd_set_auto_close(fde_read);
tevent_fd_set_auto_close(fde_write);
tevent_add_timer(ev_ctx, ev_ctx, timeval_current_ofs(2,0),
finished_handler, &finished);
#ifdef SA_RESTART
se1 = tevent_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESTART, count_handler, &alarm_count);
torture_assert(test, se1 != NULL, "failed to setup se1");
#endif
#ifdef SA_RESETHAND
se2 = tevent_add_signal(ev_ctx, ev_ctx, SIGALRM, SA_RESETHAND, count_handler, &alarm_count);
torture_assert(test, se2 != NULL, "failed to setup se2");
#endif
#ifdef SA_SIGINFO
se3 = tevent_add_signal(ev_ctx, ev_ctx, SIGUSR1, SA_SIGINFO, count_handler, &info_count);
torture_assert(test, se3 != NULL, "failed to setup se3");
#endif
write(fd[1], &c, 1);
t = timeval_current();
while (!finished) {
errno = 0;
@ -119,8 +168,10 @@ static bool test_event_context(struct torture_context *test,
}
}
talloc_free(fde);
close(fd[1]);
talloc_free(fde_read);
talloc_free(fde_write);
talloc_free(fde_read_1);
talloc_free(fde_write_1);
while (alarm_count < fde_count+1) {
if (tevent_loop_once(ev_ctx) == -1) {
@ -136,6 +187,14 @@ static bool test_event_context(struct torture_context *test,
torture_assert_int_equal(test, alarm_count, 1+fde_count, "alarm count mismatch");
#ifdef SA_RESETHAND
/*
* we do not call talloc_free(se2)
* because it is already gone,
* after triggering the event handler.
*/
#endif
#ifdef SA_SIGINFO
talloc_free(se3);
torture_assert_int_equal(test, info_count, fde_count, "info count mismatch");
@ -146,6 +205,597 @@ static bool test_event_context(struct torture_context *test,
return true;
}
struct test_event_fd1_state {
struct torture_context *tctx;
const char *backend;
struct tevent_context *ev;
int sock[2];
struct tevent_timer *te;
struct tevent_fd *fde0;
struct tevent_fd *fde1;
bool got_write;
bool got_read;
bool drain;
bool drain_done;
unsigned loop_count;
bool finished;
const char *error;
};
static void test_event_fd1_fde_handler(struct tevent_context *ev_ctx,
struct tevent_fd *fde,
uint16_t flags,
void *private_data)
{
struct test_event_fd1_state *state =
(struct test_event_fd1_state *)private_data;
if (state->drain_done) {
state->finished = true;
state->error = __location__;
return;
}
if (state->drain) {
ssize_t ret;
uint8_t c = 0;
if (!(flags & TEVENT_FD_READ)) {
state->finished = true;
state->error = __location__;
return;
}
ret = read(state->sock[0], &c, 1);
if (ret == 1) {
return;
}
/*
* end of test...
*/
tevent_fd_set_flags(fde, 0);
state->drain_done = true;
return;
}
if (!state->got_write) {
uint8_t c = 0;
if (flags != TEVENT_FD_WRITE) {
state->finished = true;
state->error = __location__;
return;
}
state->got_write = true;
/*
* we write to the other socket...
*/
write(state->sock[1], &c, 1);
TEVENT_FD_NOT_WRITEABLE(fde);
TEVENT_FD_READABLE(fde);
return;
}
if (!state->got_read) {
if (flags != TEVENT_FD_READ) {
state->finished = true;
state->error = __location__;
return;
}
state->got_read = true;
TEVENT_FD_NOT_READABLE(fde);
return;
}
state->finished = true;
state->error = __location__;
return;
}
static void test_event_fd1_finished(struct tevent_context *ev_ctx,
struct tevent_timer *te,
struct timeval tval,
void *private_data)
{
struct test_event_fd1_state *state =
(struct test_event_fd1_state *)private_data;
if (state->drain_done) {
state->finished = true;
return;
}
if (!state->got_write) {
state->finished = true;
state->error = __location__;
return;
}
if (!state->got_read) {
state->finished = true;
state->error = __location__;
return;
}
state->loop_count++;
if (state->loop_count > 3) {
state->finished = true;
state->error = __location__;
return;
}
state->got_write = false;
state->got_read = false;
tevent_fd_set_flags(state->fde0, TEVENT_FD_WRITE);
if (state->loop_count > 2) {
state->drain = true;
TALLOC_FREE(state->fde1);
TEVENT_FD_READABLE(state->fde0);
}
state->te = tevent_add_timer(state->ev, state->ev,
timeval_current_ofs(0,2000),
test_event_fd1_finished, state);
}
static bool test_event_fd1(struct torture_context *tctx,
const void *test_data)
{
struct test_event_fd1_state state;
ZERO_STRUCT(state);
state.tctx = tctx;
state.backend = (const char *)test_data;
state.ev = tevent_context_init_byname(tctx, state.backend);
if (state.ev == NULL) {
torture_skip(tctx, talloc_asprintf(tctx,
"event backend '%s' not supported\n",
state.backend));
return true;
}
tevent_set_debug_stderr(state.ev);
torture_comment(tctx, "backend '%s' - %s\n",
state.backend, __FUNCTION__);
/*
* This tests the following:
*
* It monitors the state of state.sock[0]
* with tevent_fd, but we never read/write on state.sock[0]
* while state.sock[1] * is only used to write a few bytes.
*
* We have a loop:
* - we wait only for TEVENT_FD_WRITE on state.sock[0]
* - we write 1 byte to state.sock[1]
* - we wait only for TEVENT_FD_READ on state.sock[0]
* - we disable events on state.sock[0]
* - the timer event restarts the loop
* Then we close state.sock[1]
* We have a loop:
* - we wait for TEVENT_FD_READ/WRITE on state.sock[0]
* - we try to read 1 byte
* - if the read gets an error of returns 0
* we disable the event handler
* - the timer finishes the test
*/
state.sock[0] = -1;
state.sock[1] = -1;
socketpair(AF_UNIX, SOCK_STREAM, 0, state.sock);
state.te = tevent_add_timer(state.ev, state.ev,
timeval_current_ofs(0,1000),
test_event_fd1_finished, &state);
state.fde0 = tevent_add_fd(state.ev, state.ev,
state.sock[0], TEVENT_FD_WRITE,
test_event_fd1_fde_handler, &state);
/* state.fde1 is only used to auto close */
state.fde1 = tevent_add_fd(state.ev, state.ev,
state.sock[1], 0,
test_event_fd1_fde_handler, &state);
tevent_fd_set_auto_close(state.fde0);
tevent_fd_set_auto_close(state.fde1);
while (!state.finished) {
errno = 0;
if (tevent_loop_once(state.ev) == -1) {
talloc_free(state.ev);
torture_fail(tctx, talloc_asprintf(tctx,
"Failed event loop %s\n",
strerror(errno)));
}
}
talloc_free(state.ev);
torture_assert(tctx, state.error == NULL, talloc_asprintf(tctx,
"%s", state.error));
return true;
}
struct test_event_fd2_state {
struct torture_context *tctx;
const char *backend;
struct tevent_context *ev;
struct tevent_timer *te;
struct test_event_fd2_sock {
struct test_event_fd2_state *state;
int fd;
struct tevent_fd *fde;
size_t num_written;
size_t num_read;
bool got_full;
} sock0, sock1;
bool finished;
const char *error;
};
static void test_event_fd2_sock_handler(struct tevent_context *ev_ctx,
struct tevent_fd *fde,
uint16_t flags,
void *private_data)
{
struct test_event_fd2_sock *cur_sock =
(struct test_event_fd2_sock *)private_data;
struct test_event_fd2_state *state = cur_sock->state;
struct test_event_fd2_sock *oth_sock = NULL;
uint8_t v = 0, c;
ssize_t ret;
if (cur_sock == &state->sock0) {
oth_sock = &state->sock1;
} else {
oth_sock = &state->sock0;
}
if (oth_sock->num_written == 1) {
if (flags != (TEVENT_FD_READ | TEVENT_FD_WRITE)) {
state->finished = true;
state->error = __location__;
return;
}
}
if (cur_sock->num_read == oth_sock->num_written) {
state->finished = true;
state->error = __location__;
return;
}
if (!(flags & TEVENT_FD_READ)) {
state->finished = true;
state->error = __location__;
return;
}
if (oth_sock->num_read > 0) {
/*
* There should be room to write a byte again
*/
if (!(flags & TEVENT_FD_WRITE)) {
state->finished = true;
state->error = __location__;
return;
}
}
if ((flags & TEVENT_FD_WRITE) && !cur_sock->got_full) {
v = (uint8_t)cur_sock->num_written;
ret = write(cur_sock->fd, &v, 1);
if (ret != 1) {
state->finished = true;
state->error = __location__;
return;
}
cur_sock->num_written++;
if (cur_sock->num_written > 0x80000000) {
state->finished = true;
state->error = __location__;
return;
}
return;
}
if (!cur_sock->got_full) {
cur_sock->got_full = true;
if (!oth_sock->got_full) {
/*
* cur_sock is full,
* lets wait for oth_sock
* to be filled
*/
tevent_fd_set_flags(cur_sock->fde, 0);
return;
}
/*
* oth_sock waited for cur_sock,
* lets restart it
*/
tevent_fd_set_flags(oth_sock->fde,
TEVENT_FD_READ|TEVENT_FD_WRITE);
}
ret = read(cur_sock->fd, &v, 1);
if (ret != 1) {
state->finished = true;
state->error = __location__;
return;
}
c = (uint8_t)cur_sock->num_read;
if (c != v) {
state->finished = true;
state->error = __location__;
return;
}
cur_sock->num_read++;
if (cur_sock->num_read < oth_sock->num_written) {
/* there is more to read */
return;
}
/*
* we read everything, we need to remove TEVENT_FD_WRITE
* to avoid spinning
*/
TEVENT_FD_NOT_WRITEABLE(cur_sock->fde);
if (oth_sock->num_read == cur_sock->num_written) {
/*
* both directions are finished
*/
state->finished = true;
}
return;
}
static void test_event_fd2_finished(struct tevent_context *ev_ctx,
struct tevent_timer *te,
struct timeval tval,
void *private_data)
{
struct test_event_fd2_state *state =
(struct test_event_fd2_state *)private_data;
/*
* this should never be triggered
*/
state->finished = true;
state->error = __location__;
}
static bool test_event_fd2(struct torture_context *tctx,
const void *test_data)
{
struct test_event_fd2_state state;
int sock[2];
uint8_t c = 0;
ZERO_STRUCT(state);
state.tctx = tctx;
state.backend = (const char *)test_data;
state.ev = tevent_context_init_byname(tctx, state.backend);
if (state.ev == NULL) {
torture_skip(tctx, talloc_asprintf(tctx,
"event backend '%s' not supported\n",
state.backend));
return true;
}
tevent_set_debug_stderr(state.ev);
torture_comment(tctx, "backend '%s' - %s\n",
state.backend, __FUNCTION__);
/*
* This tests the following
*
* - We write 1 byte to each socket
* - We wait for TEVENT_FD_READ/WRITE on both sockets
* - When we get TEVENT_FD_WRITE we write 1 byte
* until both socket buffers are full, which
* means both sockets only get TEVENT_FD_READ.
* - Then we read 1 byte until we have consumed
* all bytes the other end has written.
*/
sock[0] = -1;
sock[1] = -1;
socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
/*
* the timer should never expire
*/
state.te = tevent_add_timer(state.ev, state.ev,
timeval_current_ofs(600, 0),
test_event_fd2_finished, &state);
state.sock0.state = &state;
state.sock0.fd = sock[0];
state.sock0.fde = tevent_add_fd(state.ev, state.ev,
state.sock0.fd,
TEVENT_FD_READ | TEVENT_FD_WRITE,
test_event_fd2_sock_handler,
&state.sock0);
state.sock1.state = &state;
state.sock1.fd = sock[1];
state.sock1.fde = tevent_add_fd(state.ev, state.ev,
state.sock1.fd,
TEVENT_FD_READ | TEVENT_FD_WRITE,
test_event_fd2_sock_handler,
&state.sock1);
tevent_fd_set_auto_close(state.sock0.fde);
tevent_fd_set_auto_close(state.sock1.fde);
write(state.sock0.fd, &c, 1);
state.sock0.num_written++;
write(state.sock1.fd, &c, 1);
state.sock1.num_written++;
while (!state.finished) {
errno = 0;
if (tevent_loop_once(state.ev) == -1) {
talloc_free(state.ev);
torture_fail(tctx, talloc_asprintf(tctx,
"Failed event loop %s\n",
strerror(errno)));
}
}
talloc_free(state.ev);
torture_assert(tctx, state.error == NULL, talloc_asprintf(tctx,
"%s", state.error));
return true;
}
#ifdef HAVE_PTHREAD
static pthread_mutex_t threaded_mutex = PTHREAD_MUTEX_INITIALIZER;
static bool do_shutdown = false;
static void test_event_threaded_lock(void)
{
int ret;
ret = pthread_mutex_lock(&threaded_mutex);
assert(ret == 0);
}
static void test_event_threaded_unlock(void)
{
int ret;
ret = pthread_mutex_unlock(&threaded_mutex);
assert(ret == 0);
}
static void test_event_threaded_trace(enum tevent_trace_point point,
void *private_data)
{
switch (point) {
case TEVENT_TRACE_BEFORE_WAIT:
test_event_threaded_unlock();
break;
case TEVENT_TRACE_AFTER_WAIT:
test_event_threaded_lock();
break;
case TEVENT_TRACE_BEFORE_LOOP_ONCE:
case TEVENT_TRACE_AFTER_LOOP_ONCE:
break;
}
}
static void test_event_threaded_timer(struct tevent_context *ev,
struct tevent_timer *te,
struct timeval current_time,
void *private_data)
{
return;
}
static void *test_event_poll_thread(void *private_data)
{
struct tevent_context *ev = (struct tevent_context *)private_data;
test_event_threaded_lock();
while (true) {
int ret;
ret = tevent_loop_once(ev);
assert(ret == 0);
if (do_shutdown) {
test_event_threaded_unlock();
return NULL;
}
}
}
static void test_event_threaded_read_handler(struct tevent_context *ev,
struct tevent_fd *fde,
uint16_t flags,
void *private_data)
{
int *pfd = (int *)private_data;
char c;
ssize_t nread;
if ((flags & TEVENT_FD_READ) == 0) {
return;
}
do {
nread = read(*pfd, &c, 1);
} while ((nread == -1) && (errno == EINTR));
assert(nread == 1);
}
static bool test_event_context_threaded(struct torture_context *test,
const void *test_data)
{
struct tevent_context *ev;
struct tevent_timer *te;
struct tevent_fd *fde;
pthread_t poll_thread;
int fds[2];
int ret;
char c = 0;
ev = tevent_context_init_byname(test, "poll_mt");
torture_assert(test, ev != NULL, "poll_mt not supported");
tevent_set_trace_callback(ev, test_event_threaded_trace, NULL);
te = tevent_add_timer(ev, ev, timeval_current_ofs(5, 0),
test_event_threaded_timer, NULL);
torture_assert(test, te != NULL, "Could not add timer");
ret = pthread_create(&poll_thread, NULL, test_event_poll_thread, ev);
torture_assert(test, ret == 0, "Could not create poll thread");
ret = pipe(fds);
torture_assert(test, ret == 0, "Could not create pipe");
poll(NULL, 0, 100);
test_event_threaded_lock();
fde = tevent_add_fd(ev, ev, fds[0], TEVENT_FD_READ,
test_event_threaded_read_handler, &fds[0]);
torture_assert(test, fde != NULL, "Could not add fd event");
test_event_threaded_unlock();
poll(NULL, 0, 100);
write(fds[1], &c, 1);
poll(NULL, 0, 100);
test_event_threaded_lock();
do_shutdown = true;
test_event_threaded_unlock();
write(fds[1], &c, 1);
ret = pthread_join(poll_thread, NULL);
torture_assert(test, ret == 0, "pthread_join failed");
return true;
}
#endif
struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx)
{
struct torture_suite *suite = torture_suite_create(mem_ctx, "event");
@ -153,10 +803,31 @@ struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx)
int i;
for (i=0;list && list[i];i++) {
torture_suite_add_simple_tcase_const(suite, list[i],
struct torture_suite *backend_suite;
backend_suite = torture_suite_create(mem_ctx, list[i]);
torture_suite_add_simple_tcase_const(backend_suite,
"context",
test_event_context,
(const void *)list[i]);
torture_suite_add_simple_tcase_const(backend_suite,
"fd1",
test_event_fd1,
(const void *)list[i]);
torture_suite_add_simple_tcase_const(backend_suite,
"fd2",
test_event_fd2,
(const void *)list[i]);
torture_suite_add_suite(suite, backend_suite);
}
#ifdef HAVE_PTHREAD
torture_suite_add_simple_tcase_const(suite, "threaded_poll_mt",
test_event_context_threaded,
NULL);
#endif
return suite;
}

View File

@ -1,4 +1,4 @@
/*
/*
Unix SMB/CIFS implementation.
main select loop and event handling
Copyright (C) Andrew Tridgell 2003
@ -112,12 +112,43 @@ void tevent_set_default_backend(const char *backend)
*/
static void tevent_backend_init(void)
{
static bool done;
if (done) {
return;
}
done = true;
tevent_select_init();
tevent_poll_init();
tevent_standard_init();
tevent_poll_mt_init();
#ifdef HAVE_EPOLL
tevent_epoll_init();
#endif
tevent_standard_init();
}
_PRIVATE_ const struct tevent_ops *tevent_find_ops_byname(const char *name)
{
struct tevent_ops_list *e;
tevent_backend_init();
if (name == NULL) {
name = tevent_default_backend;
}
if (name == NULL) {
name = "standard";
}
for (e = tevent_backends; e != NULL; e = e->next) {
if (0 == strcmp(e->name, name)) {
return e->ops;
}
}
return NULL;
}
/*
@ -159,6 +190,7 @@ int tevent_common_context_destructor(struct tevent_context *ev)
DLIST_REMOVE(ev->fd_events, fd);
}
ev->last_zero_timer = NULL;
for (te = ev->timer_events; te; te = tn) {
tn = te->next;
te->event_ctx = NULL;
@ -242,23 +274,14 @@ struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx,
struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx,
const char *name)
{
struct tevent_ops_list *e;
const struct tevent_ops *ops;
tevent_backend_init();
if (name == NULL) {
name = tevent_default_backend;
}
if (name == NULL) {
name = "standard";
ops = tevent_find_ops_byname(name);
if (ops == NULL) {
return NULL;
}
for (e=tevent_backends;e;e=e->next) {
if (strcmp(name, e->name) == 0) {
return tevent_context_init_ops(mem_ctx, e->ops, NULL);
}
}
return NULL;
return tevent_context_init_ops(mem_ctx, ops, NULL);
}
@ -445,7 +468,7 @@ void tevent_loop_set_nesting_hook(struct tevent_context *ev,
tevent_nesting_hook hook,
void *private_data)
{
if (ev->nesting.hook_fn &&
if (ev->nesting.hook_fn &&
(ev->nesting.hook_fn != hook ||
ev->nesting.hook_private != private_data)) {
/* the way the nesting hook code is currently written
@ -471,7 +494,7 @@ static void tevent_abort_nesting(struct tevent_context *ev, const char *location
}
/*
do a single event loop using the events defined in ev
do a single event loop using the events defined in ev
*/
int _tevent_loop_once(struct tevent_context *ev, const char *location)
{
@ -503,7 +526,9 @@ int _tevent_loop_once(struct tevent_context *ev, const char *location)
}
}
tevent_trace_point_callback(ev, TEVENT_TRACE_BEFORE_LOOP_ONCE);
ret = ev->ops->loop_once(ev, location);
tevent_trace_point_callback(ev, TEVENT_TRACE_AFTER_LOOP_ONCE);
if (ev->nesting.level > 0) {
if (ev->nesting.hook_fn) {
@ -563,7 +588,9 @@ int _tevent_loop_until(struct tevent_context *ev,
}
while (!finished(private_data)) {
tevent_trace_point_callback(ev, TEVENT_TRACE_BEFORE_LOOP_ONCE);
ret = ev->ops->loop_once(ev, location);
tevent_trace_point_callback(ev, TEVENT_TRACE_AFTER_LOOP_ONCE);
if (ret != 0) {
break;
}
@ -630,7 +657,7 @@ int _tevent_loop_wait(struct tevent_context *ev, const char *location)
/*
re-initialise a tevent context. This leaves you with the same
event context, but all events are wiped and the structure is
re-initialised. This is most useful after a fork()
re-initialised. This is most useful after a fork()
zero is returned on success, non-zero on failure
*/

View File

@ -1,4 +1,4 @@
/*
/*
Unix SMB/CIFS implementation.
generalised event loop handling
@ -524,6 +524,17 @@ enum tevent_trace_point {
* Corresponds to a trace point just after waiting
*/
TEVENT_TRACE_AFTER_WAIT,
#define TEVENT_HAS_LOOP_ONCE_TRACE_POINTS 1
/**
* Corresponds to a trace point just before calling
* the loop_once() backend function.
*/
TEVENT_TRACE_BEFORE_LOOP_ONCE,
/**
* Corresponds to a trace point right after the
* loop_once() backend function has returned.
*/
TEVENT_TRACE_AFTER_LOOP_ONCE,
};
typedef void (*tevent_trace_callback_t)(enum tevent_trace_point,

View File

@ -8,5 +8,5 @@ Description: An event system library
Version: @PACKAGE_VERSION@
Requires: talloc
Libs: -L${libdir} -ltevent
Cflags: -I${includedir}
Cflags: @LIB_RPATH@ -I${includedir}
URL: http://samba.org/

29
ctdb/lib/tevent/tevent.py Normal file
View File

@ -0,0 +1,29 @@
#!/usr/bin/python
#
# Python integration for tevent
#
# Copyright (C) Jelmer Vernooij 2011
#
# ** NOTE! The following LGPL license applies to the tevent
# ** library. This does NOT imply that all of Samba is released
# ** under the LGPL
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, see <http://www.gnu.org/licenses/>.
from _tevent import (
__version__,
backend_list,
Context,
Signal,
)

View File

@ -1,10 +1,11 @@
/*
/*
Unix SMB/CIFS implementation.
main select loop and event handling - epoll implementation
Copyright (C) Andrew Tridgell 2003-2005
Copyright (C) Stefan Metzmacher 2005-2009
Copyright (C) Stefan Metzmacher 2005-2013
Copyright (C) Jeremy Allison 2013
** NOTE! The following LGPL license applies to the tevent
** library. This does NOT imply that all of Samba is released
@ -39,16 +40,140 @@ struct epoll_event_context {
int epoll_fd;
pid_t pid;
bool panic_force_replay;
bool *panic_state;
bool (*panic_fallback)(struct tevent_context *ev, bool replay);
};
#define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT (1<<0)
#define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1)
#define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2)
#define EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX (1<<3)
#ifdef TEST_PANIC_FALLBACK
static int epoll_create_panic_fallback(struct epoll_event_context *epoll_ev,
int size)
{
if (epoll_ev->panic_fallback == NULL) {
return epoll_create(size);
}
/* 50% of the time, fail... */
if ((random() % 2) == 0) {
errno = EINVAL;
return -1;
}
return epoll_create(size);
}
static int epoll_ctl_panic_fallback(struct epoll_event_context *epoll_ev,
int epfd, int op, int fd,
struct epoll_event *event)
{
if (epoll_ev->panic_fallback == NULL) {
return epoll_ctl(epfd, op, fd, event);
}
/* 50% of the time, fail... */
if ((random() % 2) == 0) {
errno = EINVAL;
return -1;
}
return epoll_ctl(epfd, op, fd, event);
}
static int epoll_wait_panic_fallback(struct epoll_event_context *epoll_ev,
int epfd,
struct epoll_event *events,
int maxevents,
int timeout)
{
if (epoll_ev->panic_fallback == NULL) {
return epoll_wait(epfd, events, maxevents, timeout);
}
/* 50% of the time, fail... */
if ((random() % 2) == 0) {
errno = EINVAL;
return -1;
}
return epoll_wait(epfd, events, maxevents, timeout);
}
#define epoll_create(_size) \
epoll_create_panic_fallback(epoll_ev, _size)
#define epoll_ctl(_epfd, _op, _fd, _event) \
epoll_ctl_panic_fallback(epoll_ev,_epfd, _op, _fd, _event)
#define epoll_wait(_epfd, _events, _maxevents, _timeout) \
epoll_wait_panic_fallback(epoll_ev, _epfd, _events, _maxevents, _timeout)
#endif
/*
called to set the panic fallback function.
*/
_PRIVATE_ bool tevent_epoll_set_panic_fallback(struct tevent_context *ev,
bool (*panic_fallback)(struct tevent_context *ev,
bool replay))
{
struct epoll_event_context *epoll_ev;
if (ev->additional_data == NULL) {
return false;
}
epoll_ev = talloc_get_type(ev->additional_data,
struct epoll_event_context);
if (epoll_ev == NULL) {
return false;
}
epoll_ev->panic_fallback = panic_fallback;
return true;
}
/*
called when a epoll call fails
*/
static void epoll_panic(struct epoll_event_context *epoll_ev, const char *reason)
static void epoll_panic(struct epoll_event_context *epoll_ev,
const char *reason, bool replay)
{
tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL,
"%s (%s) - calling abort()\n", reason, strerror(errno));
abort();
struct tevent_context *ev = epoll_ev->ev;
bool (*panic_fallback)(struct tevent_context *ev, bool replay);
panic_fallback = epoll_ev->panic_fallback;
if (epoll_ev->panic_state != NULL) {
*epoll_ev->panic_state = true;
}
if (epoll_ev->panic_force_replay) {
replay = true;
}
TALLOC_FREE(ev->additional_data);
if (panic_fallback == NULL) {
tevent_debug(ev, TEVENT_DEBUG_FATAL,
"%s (%s) replay[%u] - calling abort()\n",
reason, strerror(errno), (unsigned)replay);
abort();
}
tevent_debug(ev, TEVENT_DEBUG_ERROR,
"%s (%s) replay[%u] - calling panic_fallback\n",
reason, strerror(errno), (unsigned)replay);
if (!panic_fallback(ev, replay)) {
/* Fallback failed. */
tevent_debug(ev, TEVENT_DEBUG_FATAL,
"%s (%s) replay[%u] - calling abort()\n",
reason, strerror(errno), (unsigned)replay);
abort();
}
}
/*
@ -95,16 +220,18 @@ static int epoll_init_ctx(struct epoll_event_context *epoll_ev)
return 0;
}
static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde);
static void epoll_update_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde);
/*
reopen the epoll handle when our pid changes
see http://junkcode.samba.org/ftp/unpacked/junkcode/epoll_fork.c for an
see http://junkcode.samba.org/ftp/unpacked/junkcode/epoll_fork.c for an
demonstration of why this is needed
*/
static void epoll_check_reopen(struct epoll_event_context *epoll_ev)
{
struct tevent_fd *fde;
bool *caller_panic_state = epoll_ev->panic_state;
bool panic_triggered = false;
if (epoll_ev->pid == getpid()) {
return;
@ -113,8 +240,7 @@ static void epoll_check_reopen(struct epoll_event_context *epoll_ev)
close(epoll_ev->epoll_fd);
epoll_ev->epoll_fd = epoll_create(64);
if (epoll_ev->epoll_fd == -1) {
tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL,
"Failed to recreate epoll handle after fork\n");
epoll_panic(epoll_ev, "epoll_create() failed", false);
return;
}
@ -124,14 +250,113 @@ static void epoll_check_reopen(struct epoll_event_context *epoll_ev)
}
epoll_ev->pid = getpid();
epoll_ev->panic_state = &panic_triggered;
for (fde=epoll_ev->ev->fd_events;fde;fde=fde->next) {
epoll_add_event(epoll_ev, fde);
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
epoll_update_event(epoll_ev, fde);
if (panic_triggered) {
if (caller_panic_state != NULL) {
*caller_panic_state = true;
}
return;
}
}
epoll_ev->panic_state = NULL;
}
#define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT (1<<0)
#define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1)
#define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2)
/*
epoll cannot add the same file descriptor twice, once
with read, once with write which is allowed by the
tevent backend. Multiplex the existing fde, flag it
as such so we can search for the correct fde on
event triggering.
*/
static int epoll_add_multiplex_fd(struct epoll_event_context *epoll_ev,
struct tevent_fd *add_fde)
{
struct epoll_event event;
struct tevent_fd *mpx_fde;
int ret;
/* Find the existing fde that caused the EEXIST error. */
for (mpx_fde = epoll_ev->ev->fd_events; mpx_fde; mpx_fde = mpx_fde->next) {
if (mpx_fde->fd != add_fde->fd) {
continue;
}
if (mpx_fde == add_fde) {
continue;
}
break;
}
if (mpx_fde == NULL) {
tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL,
"can't find multiplex fde for fd[%d]",
add_fde->fd);
return -1;
}
if (mpx_fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) {
/* Logic error. Can't have more than 2 multiplexed fde's. */
tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL,
"multiplex fde for fd[%d] is already multiplexed\n",
mpx_fde->fd);
return -1;
}
/*
* The multiplex fde must have the same fd, and also
* already have an epoll event attached.
*/
if (!(mpx_fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT)) {
/* Logic error. Can't have more than 2 multiplexed fde's. */
tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL,
"multiplex fde for fd[%d] has no event\n",
mpx_fde->fd);
return -1;
}
/* Modify the mpx_fde to add in the new flags. */
ZERO_STRUCT(event);
event.events = epoll_map_flags(mpx_fde->flags);
event.events |= epoll_map_flags(add_fde->flags);
event.data.ptr = mpx_fde;
ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_MOD, mpx_fde->fd, &event);
if (ret != 0 && errno == EBADF) {
tevent_debug(epoll_ev->ev, TEVENT_DEBUG_ERROR,
"EPOLL_CTL_MOD EBADF for "
"add_fde[%p] mpx_fde[%p] fd[%d] - disabling\n",
add_fde, mpx_fde, add_fde->fd);
DLIST_REMOVE(epoll_ev->ev->fd_events, mpx_fde);
mpx_fde->event_ctx = NULL;
DLIST_REMOVE(epoll_ev->ev->fd_events, add_fde);
add_fde->event_ctx = NULL;
return 0;
} else if (ret != 0) {
return ret;
}
/*
* Make each fde->additional_data pointers point at each other
* so we can look them up from each other. They are now paired.
*/
mpx_fde->additional_data = (struct tevent_fd *)add_fde;
add_fde->additional_data = (struct tevent_fd *)mpx_fde;
/* Now flag both fde's as being multiplexed. */
mpx_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX;
add_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX;
/* we need to keep the GOT_ERROR flag */
if (mpx_fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR) {
add_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR;
}
return 0;
}
/*
add the epoll event to the given fd_event
@ -139,26 +364,70 @@ static void epoll_check_reopen(struct epoll_event_context *epoll_ev)
static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde)
{
struct epoll_event event;
int ret;
struct tevent_fd *mpx_fde = NULL;
if (epoll_ev->epoll_fd == -1) return;
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
/* if we don't want events yet, don't add an epoll_event */
if (fde->flags == 0) return;
if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) {
/*
* This is a multiplexed fde, we need to include both
* flags in the modified event.
*/
mpx_fde = talloc_get_type_abort(fde->additional_data,
struct tevent_fd);
mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
}
ZERO_STRUCT(event);
event.events = epoll_map_flags(fde->flags);
event.data.ptr = fde;
if (epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event) != 0) {
epoll_panic(epoll_ev, "EPOLL_CTL_ADD failed");
if (mpx_fde != NULL) {
event.events |= epoll_map_flags(mpx_fde->flags);
}
event.data.ptr = fde;
ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event);
if (ret != 0 && errno == EBADF) {
tevent_debug(epoll_ev->ev, TEVENT_DEBUG_ERROR,
"EPOLL_CTL_ADD EBADF for "
"fde[%p] mpx_fde[%p] fd[%d] - disabling\n",
fde, mpx_fde, fde->fd);
DLIST_REMOVE(epoll_ev->ev->fd_events, fde);
fde->event_ctx = NULL;
if (mpx_fde != NULL) {
DLIST_REMOVE(epoll_ev->ev->fd_events, mpx_fde);
mpx_fde->event_ctx = NULL;
}
return;
} else if (ret != 0 && errno == EEXIST && mpx_fde == NULL) {
ret = epoll_add_multiplex_fd(epoll_ev, fde);
if (ret != 0) {
epoll_panic(epoll_ev, "epoll_add_multiplex_fd failed",
false);
return;
}
} else if (ret != 0) {
epoll_panic(epoll_ev, "EPOLL_CTL_ADD failed", false);
return;
}
fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
/* only if we want to read we want to tell the event handler about errors */
if (fde->flags & TEVENT_FD_READ) {
fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
}
if (mpx_fde == NULL) {
return;
}
mpx_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
/* only if we want to read we want to tell the event handler about errors */
if (mpx_fde->flags & TEVENT_FD_READ) {
mpx_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
}
}
/*
@ -167,23 +436,50 @@ static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_
static void epoll_del_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde)
{
struct epoll_event event;
int ret;
struct tevent_fd *mpx_fde = NULL;
if (epoll_ev->epoll_fd == -1) return;
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
/* if there's no epoll_event, we don't need to delete it */
if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT)) return;
if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) {
/*
* This is a multiplexed fde, we need to modify both events.
*/
mpx_fde = talloc_get_type_abort(fde->additional_data,
struct tevent_fd);
mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
}
ZERO_STRUCT(event);
event.events = epoll_map_flags(fde->flags);
event.data.ptr = fde;
if (epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event) != 0) {
tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL,
"epoll_del_event failed! probable early close bug (%s)\n",
strerror(errno));
ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event);
if (ret != 0 && errno == ENOENT) {
/*
* This can happen after a epoll_check_reopen
* within epoll_event_fd_destructor.
*/
tevent_debug(epoll_ev->ev, TEVENT_DEBUG_TRACE,
"EPOLL_CTL_DEL ignoring ENOENT for fd[%d]\n",
fde->fd);
return;
} else if (ret != 0 && errno == EBADF) {
tevent_debug(epoll_ev->ev, TEVENT_DEBUG_WARNING,
"EPOLL_CTL_DEL EBADF for "
"fde[%p] mpx_fde[%p] fd[%d] - disabling\n",
fde, mpx_fde, fde->fd);
DLIST_REMOVE(epoll_ev->ev->fd_events, fde);
fde->event_ctx = NULL;
if (mpx_fde != NULL) {
DLIST_REMOVE(epoll_ev->ev->fd_events, mpx_fde);
mpx_fde->event_ctx = NULL;
}
return;
} else if (ret != 0) {
epoll_panic(epoll_ev, "EPOLL_CTL_DEL failed", false);
return;
}
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
}
/*
@ -191,33 +487,88 @@ static void epoll_del_event(struct epoll_event_context *epoll_ev, struct tevent_
*/
static void epoll_mod_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde)
{
struct tevent_fd *mpx_fde = NULL;
struct epoll_event event;
if (epoll_ev->epoll_fd == -1) return;
int ret;
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) {
/*
* This is a multiplexed fde, we need to include both
* flags in the modified event.
*/
mpx_fde = talloc_get_type_abort(fde->additional_data,
struct tevent_fd);
mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
}
ZERO_STRUCT(event);
event.events = epoll_map_flags(fde->flags);
if (mpx_fde != NULL) {
event.events |= epoll_map_flags(mpx_fde->flags);
}
event.data.ptr = fde;
if (epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) {
epoll_panic(epoll_ev, "EPOLL_CTL_MOD failed");
ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event);
if (ret != 0 && errno == EBADF) {
tevent_debug(epoll_ev->ev, TEVENT_DEBUG_ERROR,
"EPOLL_CTL_MOD EBADF for "
"fde[%p] mpx_fde[%p] fd[%d] - disabling\n",
fde, mpx_fde, fde->fd);
DLIST_REMOVE(epoll_ev->ev->fd_events, fde);
fde->event_ctx = NULL;
if (mpx_fde != NULL) {
DLIST_REMOVE(epoll_ev->ev->fd_events, mpx_fde);
mpx_fde->event_ctx = NULL;
}
return;
} else if (ret != 0) {
epoll_panic(epoll_ev, "EPOLL_CTL_MOD failed", false);
return;
}
fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
/* only if we want to read we want to tell the event handler about errors */
if (fde->flags & TEVENT_FD_READ) {
fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
}
if (mpx_fde == NULL) {
return;
}
mpx_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
/* only if we want to read we want to tell the event handler about errors */
if (mpx_fde->flags & TEVENT_FD_READ) {
mpx_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
}
}
static void epoll_change_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde)
static void epoll_update_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde)
{
bool got_error = (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR);
bool want_read = (fde->flags & TEVENT_FD_READ);
bool want_write= (fde->flags & TEVENT_FD_WRITE);
struct tevent_fd *mpx_fde = NULL;
if (epoll_ev->epoll_fd == -1) return;
if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) {
/*
* work out what the multiplexed fde wants.
*/
mpx_fde = talloc_get_type_abort(fde->additional_data,
struct tevent_fd);
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
if (mpx_fde->flags & TEVENT_FD_READ) {
want_read = true;
}
if (mpx_fde->flags & TEVENT_FD_WRITE) {
want_write = true;
}
}
/* there's already an event */
if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT) {
@ -225,7 +576,7 @@ static void epoll_change_event(struct epoll_event_context *epoll_ev, struct teve
epoll_mod_event(epoll_ev, fde);
return;
}
/*
/*
* if we want to match the select behavior, we need to remove the epoll_event
* when the caller isn't interested in events.
*
@ -242,6 +593,38 @@ static void epoll_change_event(struct epoll_event_context *epoll_ev, struct teve
}
}
/*
Cope with epoll returning EPOLLHUP|EPOLLERR on an event.
Return true if there's nothing else to do, false if
this event needs further handling.
*/
static bool epoll_handle_hup_or_err(struct epoll_event_context *epoll_ev,
struct tevent_fd *fde)
{
if (fde == NULL) {
/* Nothing to do if no event. */
return true;
}
fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR;
/*
* if we only wait for TEVENT_FD_WRITE, we should not tell the
* event handler about it, and remove the epoll_event,
* as we only report errors when waiting for read events,
* to match the select() behavior
*/
if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) {
/*
* Do the same as the poll backend and
* remove the writeable flag.
*/
fde->flags &= ~TEVENT_FD_WRITE;
return true;
}
/* This has TEVENT_FD_READ set, we're not finished. */
return false;
}
/*
event loop handling using epoll
*/
@ -251,11 +634,10 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval
#define MAXEVENTS 1
struct epoll_event events[MAXEVENTS];
int timeout = -1;
if (epoll_ev->epoll_fd == -1) return -1;
int wait_errno;
if (tvalp) {
/* it's better to trigger timed events a bit later than to early */
/* it's better to trigger timed events a bit later than too early */
timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
}
@ -266,16 +648,17 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval
tevent_trace_point_callback(epoll_ev->ev, TEVENT_TRACE_BEFORE_WAIT);
ret = epoll_wait(epoll_ev->epoll_fd, events, MAXEVENTS, timeout);
wait_errno = errno;
tevent_trace_point_callback(epoll_ev->ev, TEVENT_TRACE_AFTER_WAIT);
if (ret == -1 && errno == EINTR && epoll_ev->ev->signal_events) {
if (ret == -1 && wait_errno == EINTR && epoll_ev->ev->signal_events) {
if (tevent_common_check_signal(epoll_ev->ev)) {
return 0;
}
}
if (ret == -1 && errno != EINTR) {
epoll_panic(epoll_ev, "epoll_wait() failed");
if (ret == -1 && wait_errno != EINTR) {
epoll_panic(epoll_ev, "epoll_wait() failed", true);
return -1;
}
@ -286,30 +669,69 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval
}
for (i=0;i<ret;i++) {
struct tevent_fd *fde = talloc_get_type(events[i].data.ptr,
struct tevent_fd *fde = talloc_get_type(events[i].data.ptr,
struct tevent_fd);
uint16_t flags = 0;
struct tevent_fd *mpx_fde = NULL;
if (fde == NULL) {
epoll_panic(epoll_ev, "epoll_wait() gave bad data");
epoll_panic(epoll_ev, "epoll_wait() gave bad data", true);
return -1;
}
if (events[i].events & (EPOLLHUP|EPOLLERR)) {
fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR;
if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) {
/*
* if we only wait for TEVENT_FD_WRITE, we should not tell the
* event handler about it, and remove the epoll_event,
* as we only report errors when waiting for read events,
* to match the select() behavior
* Save off the multiplexed event in case we need
* to use it to call the handler function.
*/
if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) {
epoll_del_event(epoll_ev, fde);
mpx_fde = talloc_get_type_abort(fde->additional_data,
struct tevent_fd);
}
if (events[i].events & (EPOLLHUP|EPOLLERR)) {
bool handled_fde = epoll_handle_hup_or_err(epoll_ev, fde);
bool handled_mpx = epoll_handle_hup_or_err(epoll_ev, mpx_fde);
if (handled_fde && handled_mpx) {
epoll_update_event(epoll_ev, fde);
continue;
}
if (!handled_mpx) {
/*
* If the mpx event was the one that needs
* further handling, it's the TEVENT_FD_READ
* event so switch over and call that handler.
*/
fde = mpx_fde;
mpx_fde = NULL;
}
flags |= TEVENT_FD_READ;
}
if (events[i].events & EPOLLIN) flags |= TEVENT_FD_READ;
if (events[i].events & EPOLLOUT) flags |= TEVENT_FD_WRITE;
if (flags & TEVENT_FD_WRITE) {
if (fde->flags & TEVENT_FD_WRITE) {
mpx_fde = NULL;
}
if (mpx_fde && mpx_fde->flags & TEVENT_FD_WRITE) {
fde = mpx_fde;
mpx_fde = NULL;
}
}
if (mpx_fde) {
/* Ensure we got the right fde. */
if ((flags & fde->flags) == 0) {
fde = mpx_fde;
mpx_fde = NULL;
}
}
/*
* make sure we only pass the flags
* the handler is expecting.
*/
flags &= fde->flags;
if (flags) {
fde->handler(epoll_ev->ev, fde, flags, fde->private_data);
break;
@ -327,6 +749,12 @@ static int epoll_event_context_init(struct tevent_context *ev)
int ret;
struct epoll_event_context *epoll_ev;
/*
* We might be called during tevent_re_initialise()
* which means we need to free our old additional_data.
*/
TALLOC_FREE(ev->additional_data);
epoll_ev = talloc_zero(ev, struct epoll_event_context);
if (!epoll_ev) return -1;
epoll_ev->ev = ev;
@ -349,16 +777,58 @@ static int epoll_event_fd_destructor(struct tevent_fd *fde)
{
struct tevent_context *ev = fde->event_ctx;
struct epoll_event_context *epoll_ev = NULL;
bool panic_triggered = false;
struct tevent_fd *mpx_fde = NULL;
int flags = fde->flags;
if (ev) {
epoll_ev = talloc_get_type(ev->additional_data,
struct epoll_event_context);
epoll_check_reopen(epoll_ev);
epoll_del_event(epoll_ev, fde);
if (ev == NULL) {
return tevent_common_fd_destructor(fde);
}
epoll_ev = talloc_get_type_abort(ev->additional_data,
struct epoll_event_context);
/*
* we must remove the event from the list
* otherwise a panic fallback handler may
* reuse invalid memory
*/
DLIST_REMOVE(ev->fd_events, fde);
if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) {
mpx_fde = talloc_get_type_abort(fde->additional_data,
struct tevent_fd);
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX;
mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX;
fde->additional_data = NULL;
mpx_fde->additional_data = NULL;
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
}
epoll_ev->panic_state = &panic_triggered;
epoll_check_reopen(epoll_ev);
if (panic_triggered) {
return tevent_common_fd_destructor(fde);
}
if (mpx_fde != NULL) {
epoll_update_event(epoll_ev, mpx_fde);
if (panic_triggered) {
return tevent_common_fd_destructor(fde);
}
}
fde->flags = 0;
epoll_update_event(epoll_ev, fde);
fde->flags = flags;
if (panic_triggered) {
return tevent_common_fd_destructor(fde);
}
epoll_ev->panic_state = NULL;
return tevent_common_fd_destructor(fde);
}
@ -376,8 +846,7 @@ static struct tevent_fd *epoll_event_add_fd(struct tevent_context *ev, TALLOC_CT
struct epoll_event_context *epoll_ev = talloc_get_type(ev->additional_data,
struct epoll_event_context);
struct tevent_fd *fde;
epoll_check_reopen(epoll_ev);
bool panic_triggered = false;
fde = tevent_common_add_fd(ev, mem_ctx, fd, flags,
handler, private_data,
@ -386,7 +855,14 @@ static struct tevent_fd *epoll_event_add_fd(struct tevent_context *ev, TALLOC_CT
talloc_set_destructor(fde, epoll_event_fd_destructor);
epoll_add_event(epoll_ev, fde);
epoll_ev->panic_state = &panic_triggered;
epoll_check_reopen(epoll_ev);
if (panic_triggered) {
return fde;
}
epoll_ev->panic_state = NULL;
epoll_update_event(epoll_ev, fde);
return fde;
}
@ -398,6 +874,7 @@ static void epoll_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
{
struct tevent_context *ev;
struct epoll_event_context *epoll_ev;
bool panic_triggered = false;
if (fde->flags == flags) return;
@ -406,19 +883,25 @@ static void epoll_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
fde->flags = flags;
epoll_ev->panic_state = &panic_triggered;
epoll_check_reopen(epoll_ev);
if (panic_triggered) {
return;
}
epoll_ev->panic_state = NULL;
epoll_change_event(epoll_ev, fde);
epoll_update_event(epoll_ev, fde);
}
/*
do a single event loop using the events defined in ev
do a single event loop using the events defined in ev
*/
static int epoll_event_loop_once(struct tevent_context *ev, const char *location)
{
struct epoll_event_context *epoll_ev = talloc_get_type(ev->additional_data,
struct epoll_event_context);
struct epoll_event_context);
struct timeval tval;
bool panic_triggered = false;
if (ev->signal_events &&
tevent_common_check_signal(ev)) {
@ -435,7 +918,15 @@ static int epoll_event_loop_once(struct tevent_context *ev, const char *location
return 0;
}
epoll_ev->panic_state = &panic_triggered;
epoll_ev->panic_force_replay = true;
epoll_check_reopen(epoll_ev);
if (panic_triggered) {
errno = EINVAL;
return -1;
}
epoll_ev->panic_force_replay = false;
epoll_ev->panic_state = NULL;
return epoll_event_loop(epoll_ev, &tval);
}
@ -446,7 +937,7 @@ static const struct tevent_ops epoll_event_ops = {
.set_fd_close_fn = tevent_common_fd_set_close_fn,
.get_fd_flags = tevent_common_fd_get_flags,
.set_fd_flags = epoll_event_set_fd_flags,
.add_timer = tevent_common_add_timer,
.add_timer = tevent_common_add_timer_v2,
.schedule_immediate = tevent_common_schedule_immediate,
.add_signal = tevent_common_add_signal,
.loop_once = epoll_event_loop_once,

View File

@ -136,3 +136,4 @@ bool tevent_common_loop_immediate(struct tevent_context *ev)
return true;
}

View File

@ -1,10 +1,10 @@
/*
/*
Unix SMB/CIFS implementation.
generalised event loop handling
INTERNAL STRUCTS. THERE ARE NO API GUARANTEES.
External users should only ever have to include this header when
External users should only ever have to include this header when
implementing new tevent backends.
Copyright (C) Stefan Metzmacher 2005-2009
@ -263,8 +263,16 @@ struct tevent_context {
tevent_trace_callback_t callback;
void *private_data;
} tracing;
/*
* an optimization pointer into timer_events
* used by used by common code via
* tevent_common_add_timer_v2()
*/
struct tevent_timer *last_zero_timer;
};
const struct tevent_ops *tevent_find_ops_byname(const char *name);
int tevent_common_context_destructor(struct tevent_context *ev);
int tevent_common_loop_wait(struct tevent_context *ev,
@ -291,6 +299,13 @@ struct tevent_timer *tevent_common_add_timer(struct tevent_context *ev,
void *private_data,
const char *handler_name,
const char *location);
struct tevent_timer *tevent_common_add_timer_v2(struct tevent_context *ev,
TALLOC_CTX *mem_ctx,
struct timeval next_event,
tevent_timer_handler_t handler,
void *private_data,
const char *handler_name,
const char *location);
struct timeval tevent_common_loop_timer_delay(struct tevent_context *);
void tevent_common_schedule_immediate(struct tevent_immediate *im,
@ -315,9 +330,16 @@ void tevent_cleanup_pending_signal_handlers(struct tevent_signal *se);
bool tevent_standard_init(void);
bool tevent_select_init(void);
bool tevent_poll_init(void);
void tevent_poll_event_add_fd_internal(struct tevent_context *ev,
struct tevent_fd *fde);
bool tevent_poll_mt_init(void);
#ifdef HAVE_EPOLL
bool tevent_epoll_init(void);
bool tevent_epoll_set_panic_fallback(struct tevent_context *ev,
bool (*panic_fallback)(struct tevent_context *ev,
bool replay));
#endif
void tevent_trace_point_callback(struct tevent_context *ev,
enum tevent_trace_point);

View File

@ -1,7 +1,7 @@
/*
/*
Unix SMB/CIFS implementation.
main select loop and event handling
wrapper for http://liboop.org/
wrapper for http://git.lysator.liu.se/liboop/
Copyright (C) Stefan Metzmacher 2005
@ -29,12 +29,12 @@
#include <oop.h>
/*
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
NOTE: this code compiles fine, but is completely *UNTESTED*
and is only committed as an example
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
*/
static int oop_event_context_destructor(struct tevent_context *ev)
@ -79,7 +79,7 @@ static void *oop_event_fd_handler(oop_source *oop, int fd, oop_event oop_type, v
return OOP_CONTINUE;
case OOP_WRITE:
fde->handler(fde->event_ctx, fde, EVENT_FD_WRITE, fde->private_data);
return OOP_CONTINUE;
return OOP_CONTINUE;
case OOP_EXCEPTION:
return OOP_ERROR;
case OOP_NUM_EVENTS:
@ -123,7 +123,7 @@ static struct tevent_fd *oop_event_add_fd(struct tevent_context *ev, TALLOC_CTX
struct tevent_fd *fde;
oop_source_sys *oop_sys = ev->additional_data;
oop_source *oop = oop_sys_source(oop_sys);
fde = talloc(mem_ctx?mem_ctx:ev, struct tevent_fd);
if (!fde) return NULL;
@ -219,9 +219,9 @@ static int oop_event_timed_destructor(struct tevent_timer *te)
return NULL on failure (memory allocation error)
*/
static struct tevent_timer *oop_event_add_timed(struct tevent_context *ev, TALLOC_CTX *mem_ctx,
struct timeval next_event,
event_timed_handler_t handler,
void *private_data)
struct timeval next_event,
event_timed_handler_t handler,
void *private_data)
{
oop_source_sys *oop_sys = ev->additional_data;
oop_source *oop = oop_sys_source(oop_sys);
@ -244,7 +244,7 @@ static struct tevent_timer *oop_event_add_timed(struct tevent_context *ev, TALLO
}
/*
do a single event loop using the events defined in ev
do a single event loop using the events defined in ev
*/
static int oop_event_loop_once(struct tevent_context *ev)
{

View File

@ -33,41 +33,196 @@ struct poll_event_context {
/* a pointer back to the generic event_context */
struct tevent_context *ev;
/*
* A DLIST for fresh fde's added by poll_event_add_fd but not
* picked up yet by poll_event_loop_once
*/
struct tevent_fd *fresh;
/*
* A DLIST for disabled fde's.
*/
struct tevent_fd *disabled;
/*
* one or more events were deleted or disabled
*/
bool deleted;
/*
* These two arrays are maintained together.
*/
struct pollfd *fds;
struct tevent_fd **fd_events;
uint64_t num_fds;
struct tevent_fd **fdes;
unsigned num_fds;
/*
* Signal fd to wake the poll() thread
*/
int signal_fd;
/* information for exiting from the event loop */
int exit_code;
};
static int poll_event_context_destructor(struct poll_event_context *poll_ev)
{
struct tevent_fd *fd, *fn;
for (fd = poll_ev->fresh; fd; fd = fn) {
fn = fd->next;
fd->event_ctx = NULL;
DLIST_REMOVE(poll_ev->fresh, fd);
}
for (fd = poll_ev->disabled; fd; fd = fn) {
fn = fd->next;
fd->event_ctx = NULL;
DLIST_REMOVE(poll_ev->disabled, fd);
}
if (poll_ev->signal_fd == -1) {
/*
* Non-threaded, no signal pipe
*/
return 0;
}
close(poll_ev->signal_fd);
poll_ev->signal_fd = -1;
if (poll_ev->num_fds == 0) {
return 0;
}
if (poll_ev->fds[0].fd != -1) {
close(poll_ev->fds[0].fd);
poll_ev->fds[0].fd = -1;
}
return 0;
}
/*
create a select_event_context structure.
create a poll_event_context structure.
*/
static int poll_event_context_init(struct tevent_context *ev)
{
struct poll_event_context *poll_ev;
/*
* we might be called during tevent_re_initialise()
* which means we need to free our old additional_data
* in order to detach old fd events from the
* poll_ev->fresh list
*/
TALLOC_FREE(ev->additional_data);
poll_ev = talloc_zero(ev, struct poll_event_context);
if (poll_ev == NULL) {
return -1;
}
poll_ev->ev = ev;
poll_ev->signal_fd = -1;
ev->additional_data = poll_ev;
talloc_set_destructor(poll_ev, poll_event_context_destructor);
return 0;
}
static bool set_nonblock(int fd)
{
int val;
val = fcntl(fd, F_GETFL, 0);
if (val == -1) {
return false;
}
val |= O_NONBLOCK;
return (fcntl(fd, F_SETFL, val) != -1);
}
static int poll_event_context_init_mt(struct tevent_context *ev)
{
struct poll_event_context *poll_ev;
struct pollfd *pfd;
int fds[2];
int ret;
ret = poll_event_context_init(ev);
if (ret == -1) {
return ret;
}
poll_ev = talloc_get_type_abort(
ev->additional_data, struct poll_event_context);
poll_ev->fds = talloc_zero(poll_ev, struct pollfd);
if (poll_ev->fds == NULL) {
return -1;
}
ret = pipe(fds);
if (ret == -1) {
return -1;
}
if (!set_nonblock(fds[0]) || !set_nonblock(fds[1])) {
close(fds[0]);
close(fds[1]);
return -1;
}
poll_ev->signal_fd = fds[1];
pfd = &poll_ev->fds[0];
pfd->fd = fds[0];
pfd->events = (POLLIN|POLLHUP);
poll_ev->num_fds = 1;
talloc_set_destructor(poll_ev, poll_event_context_destructor);
return 0;
}
static void poll_event_wake_pollthread(struct poll_event_context *poll_ev)
{
char c;
ssize_t ret;
if (poll_ev->signal_fd == -1) {
return;
}
c = 0;
do {
ret = write(poll_ev->signal_fd, &c, sizeof(c));
} while ((ret == -1) && (errno == EINTR));
}
static void poll_event_drain_signal_fd(struct poll_event_context *poll_ev)
{
char buf[16];
ssize_t ret;
int fd;
if (poll_ev->signal_fd == -1) {
return;
}
if (poll_ev->num_fds < 1) {
return;
}
fd = poll_ev->fds[0].fd;
do {
ret = read(fd, buf, sizeof(buf));
} while (ret == sizeof(buf));
}
/*
destroy an fd_event
*/
static int poll_event_fd_destructor(struct tevent_fd *fde)
{
struct tevent_context *ev = fde->event_ctx;
struct poll_event_context *poll_ev = NULL;
struct tevent_fd *moved_fde;
struct poll_event_context *poll_ev;
uint64_t del_idx = fde->additional_flags;
if (ev == NULL) {
@ -77,16 +232,60 @@ static int poll_event_fd_destructor(struct tevent_fd *fde)
poll_ev = talloc_get_type_abort(
ev->additional_data, struct poll_event_context);
moved_fde = poll_ev->fd_events[poll_ev->num_fds-1];
poll_ev->fd_events[del_idx] = moved_fde;
poll_ev->fds[del_idx] = poll_ev->fds[poll_ev->num_fds-1];
moved_fde->additional_flags = del_idx;
if (del_idx == UINT64_MAX) {
struct tevent_fd **listp =
(struct tevent_fd **)fde->additional_data;
poll_ev->num_fds -= 1;
DLIST_REMOVE((*listp), fde);
goto done;
}
poll_ev->fdes[del_idx] = NULL;
poll_ev->deleted = true;
poll_event_wake_pollthread(poll_ev);
done:
return tevent_common_fd_destructor(fde);
}
static void poll_event_schedule_immediate(struct tevent_immediate *im,
struct tevent_context *ev,
tevent_immediate_handler_t handler,
void *private_data,
const char *handler_name,
const char *location)
{
struct poll_event_context *poll_ev = talloc_get_type_abort(
ev->additional_data, struct poll_event_context);
tevent_common_schedule_immediate(im, ev, handler, private_data,
handler_name, location);
poll_event_wake_pollthread(poll_ev);
}
/*
Private function called by "standard" backend fallback.
Note this only allows fallback to "poll" backend, not "poll-mt".
*/
_PRIVATE_ void tevent_poll_event_add_fd_internal(struct tevent_context *ev,
struct tevent_fd *fde)
{
struct poll_event_context *poll_ev = talloc_get_type_abort(
ev->additional_data, struct poll_event_context);
struct tevent_fd **listp;
if (fde->flags != 0) {
listp = &poll_ev->fresh;
} else {
listp = &poll_ev->disabled;
}
fde->additional_flags = UINT64_MAX;
fde->additional_data = listp;
DLIST_ADD((*listp), fde);
talloc_set_destructor(fde, poll_event_fd_destructor);
}
/*
add a fd based event
return NULL on failure (memory allocation error)
@ -101,60 +300,34 @@ static struct tevent_fd *poll_event_add_fd(struct tevent_context *ev,
{
struct poll_event_context *poll_ev = talloc_get_type_abort(
ev->additional_data, struct poll_event_context);
struct pollfd *pfd;
struct tevent_fd *fde;
fde = tevent_common_add_fd(ev, mem_ctx, fd, flags,
handler, private_data,
handler_name, location);
if (fde == NULL) {
if (fd < 0) {
return NULL;
}
/* we allocate 16 slots to avoid a lot of reallocations */
if (talloc_array_length(poll_ev->fds) == poll_ev->num_fds) {
struct pollfd *tmp_fds;
struct tevent_fd **tmp_fd_events;
tmp_fds = talloc_realloc(
poll_ev, poll_ev->fds, struct pollfd,
poll_ev->num_fds + 16);
if (tmp_fds == NULL) {
TALLOC_FREE(fde);
return NULL;
}
poll_ev->fds = tmp_fds;
tmp_fd_events = talloc_realloc(
poll_ev, poll_ev->fd_events, struct tevent_fd *,
poll_ev->num_fds + 16);
if (tmp_fd_events == NULL) {
TALLOC_FREE(fde);
return NULL;
}
poll_ev->fd_events = tmp_fd_events;
fde = talloc(mem_ctx ? mem_ctx : ev, struct tevent_fd);
if (fde == NULL) {
return NULL;
}
fde->event_ctx = ev;
fde->fd = fd;
fde->flags = flags;
fde->handler = handler;
fde->close_fn = NULL;
fde->private_data = private_data;
fde->handler_name = handler_name;
fde->location = location;
fde->additional_flags = UINT64_MAX;
fde->additional_data = NULL;
pfd = &poll_ev->fds[poll_ev->num_fds];
pfd->fd = fd;
pfd->events = 0;
pfd->revents = 0;
if (flags & TEVENT_FD_READ) {
pfd->events |= (POLLIN|POLLHUP);
}
if (flags & TEVENT_FD_WRITE) {
pfd->events |= (POLLOUT);
}
fde->additional_flags = poll_ev->num_fds;
poll_ev->fd_events[poll_ev->num_fds] = fde;
poll_ev->num_fds += 1;
talloc_set_destructor(fde, poll_event_fd_destructor);
tevent_poll_event_add_fd_internal(ev, fde);
poll_event_wake_pollthread(poll_ev);
/*
* poll_event_loop_poll will take care of the rest in
* poll_event_setup_fresh
*/
return fde;
}
@ -163,10 +336,46 @@ static struct tevent_fd *poll_event_add_fd(struct tevent_context *ev,
*/
static void poll_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
{
struct poll_event_context *poll_ev = talloc_get_type_abort(
fde->event_ctx->additional_data, struct poll_event_context);
struct tevent_context *ev = fde->event_ctx;
struct poll_event_context *poll_ev;
uint64_t idx = fde->additional_flags;
uint16_t pollflags = 0;
uint16_t pollflags;
if (ev == NULL) {
return;
}
poll_ev = talloc_get_type_abort(
ev->additional_data, struct poll_event_context);
fde->flags = flags;
if (idx == UINT64_MAX) {
struct tevent_fd **listp =
(struct tevent_fd **)fde->additional_data;
/*
* We move it between the fresh and disabled lists.
*/
DLIST_REMOVE((*listp), fde);
tevent_poll_event_add_fd_internal(ev, fde);
poll_event_wake_pollthread(poll_ev);
return;
}
if (fde->flags == 0) {
/*
* We need to remove it from the array
* and move it to the disabled list.
*/
poll_ev->fdes[idx] = NULL;
poll_ev->deleted = true;
DLIST_REMOVE(ev->fd_events, fde);
tevent_poll_event_add_fd_internal(ev, fde);
poll_event_wake_pollthread(poll_ev);
return;
}
pollflags = 0;
if (flags & TEVENT_FD_READ) {
pollflags |= (POLLIN|POLLHUP);
@ -174,10 +383,110 @@ static void poll_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
if (flags & TEVENT_FD_WRITE) {
pollflags |= (POLLOUT);
}
poll_ev->fds[idx].events = pollflags;
fde->flags = flags;
poll_event_wake_pollthread(poll_ev);
}
static bool poll_event_setup_fresh(struct tevent_context *ev,
struct poll_event_context *poll_ev)
{
struct tevent_fd *fde, *next;
unsigned num_fresh, num_fds;
if (poll_ev->deleted) {
unsigned first_fd = (poll_ev->signal_fd != -1) ? 1 : 0;
unsigned i;
for (i=first_fd; i < poll_ev->num_fds;) {
fde = poll_ev->fdes[i];
if (fde != NULL) {
i++;
continue;
}
/*
* This fde was talloc_free()'ed. Delete it
* from the arrays
*/
poll_ev->num_fds -= 1;
if (poll_ev->num_fds == i) {
break;
}
poll_ev->fds[i] = poll_ev->fds[poll_ev->num_fds];
poll_ev->fdes[i] = poll_ev->fdes[poll_ev->num_fds];
if (poll_ev->fdes[i] != NULL) {
poll_ev->fdes[i]->additional_flags = i;
}
}
}
poll_ev->deleted = false;
if (poll_ev->fresh == NULL) {
return true;
}
num_fresh = 0;
for (fde = poll_ev->fresh; fde; fde = fde->next) {
num_fresh += 1;
}
num_fds = poll_ev->num_fds + num_fresh;
/*
* We check the length of fdes here. It is the last one
* enlarged, so if the realloc for poll_fd->fdes fails,
* poll_fd->fds will have at least the size of poll_fd->fdes
*/
if (num_fds >= talloc_array_length(poll_ev->fdes)) {
struct pollfd *tmp_fds;
struct tevent_fd **tmp_fdes;
unsigned array_length;
array_length = (num_fds + 15) & ~15; /* round up to 16 */
tmp_fds = talloc_realloc(
poll_ev, poll_ev->fds, struct pollfd, array_length);
if (tmp_fds == NULL) {
return false;
}
poll_ev->fds = tmp_fds;
tmp_fdes = talloc_realloc(
poll_ev, poll_ev->fdes, struct tevent_fd *,
array_length);
if (tmp_fdes == NULL) {
return false;
}
poll_ev->fdes = tmp_fdes;
}
for (fde = poll_ev->fresh; fde; fde = next) {
struct pollfd *pfd;
pfd = &poll_ev->fds[poll_ev->num_fds];
pfd->fd = fde->fd;
pfd->events = 0;
pfd->revents = 0;
if (fde->flags & TEVENT_FD_READ) {
pfd->events |= (POLLIN|POLLHUP);
}
if (fde->flags & TEVENT_FD_WRITE) {
pfd->events |= (POLLOUT);
}
fde->additional_flags = poll_ev->num_fds;
poll_ev->fdes[poll_ev->num_fds] = fde;
next = fde->next;
DLIST_REMOVE(poll_ev->fresh, fde);
DLIST_ADD(ev->fd_events, fde);
poll_ev->num_fds += 1;
}
return true;
}
/*
@ -188,9 +497,11 @@ static int poll_event_loop_poll(struct tevent_context *ev,
{
struct poll_event_context *poll_ev = talloc_get_type_abort(
ev->additional_data, struct poll_event_context);
struct tevent_fd *fde;
int pollrtn;
int timeout = -1;
int poll_errno;
struct tevent_fd *fde = NULL;
unsigned i;
if (ev->signal_events && tevent_common_check_signal(ev)) {
return 0;
@ -201,25 +512,20 @@ static int poll_event_loop_poll(struct tevent_context *ev,
timeout += (tvalp->tv_usec + 999) / 1000;
}
tevent_trace_point_callback(poll_ev->ev, TEVENT_TRACE_BEFORE_WAIT);
pollrtn = poll(poll_ev->fds, poll_ev->num_fds, timeout);
tevent_trace_point_callback(poll_ev->ev, TEVENT_TRACE_AFTER_WAIT);
poll_event_drain_signal_fd(poll_ev);
if (pollrtn == -1 && errno == EINTR && ev->signal_events) {
tevent_common_check_signal(ev);
return 0;
if (!poll_event_setup_fresh(ev, poll_ev)) {
return -1;
}
if (pollrtn == -1 && errno == EBADF) {
/* the socket is dead! this should never
happen as the socket should have first been
made readable and that should have removed
the event, so this must be a bug. This is a
fatal error. */
tevent_debug(ev, TEVENT_DEBUG_FATAL,
"ERROR: EBADF on poll_event_loop_once\n");
poll_ev->exit_code = EBADF;
return -1;
tevent_trace_point_callback(poll_ev->ev, TEVENT_TRACE_BEFORE_WAIT);
pollrtn = poll(poll_ev->fds, poll_ev->num_fds, timeout);
poll_errno = errno;
tevent_trace_point_callback(poll_ev->ev, TEVENT_TRACE_AFTER_WAIT);
if (pollrtn == -1 && poll_errno == EINTR && ev->signal_events) {
tevent_common_check_signal(ev);
return 0;
}
if (pollrtn == 0 && tvalp) {
@ -240,11 +546,35 @@ static int poll_event_loop_poll(struct tevent_context *ev,
the handler to remove itself when called */
for (fde = ev->fd_events; fde; fde = fde->next) {
unsigned idx = fde->additional_flags;
struct pollfd *pfd;
uint64_t pfd_idx = fde->additional_flags;
uint16_t flags = 0;
pfd = &poll_ev->fds[pfd_idx];
if (idx == UINT64_MAX) {
continue;
}
pfd = &poll_ev->fds[idx];
if (pfd->revents & POLLNVAL) {
/*
* the socket is dead! this should never
* happen as the socket should have first been
* made readable and that should have removed
* the event, so this must be a bug.
*
* We ignore it here to match the epoll
* behavior.
*/
tevent_debug(ev, TEVENT_DEBUG_ERROR,
"POLLNVAL on fde[%p] fd[%d] - disabling\n",
fde, pfd->fd);
poll_ev->fdes[idx] = NULL;
poll_ev->deleted = true;
DLIST_REMOVE(ev->fd_events, fde);
fde->event_ctx = NULL;
continue;
}
if (pfd->revents & (POLLHUP|POLLERR)) {
/* If we only wait for TEVENT_FD_WRITE, we
@ -264,9 +594,38 @@ static int poll_event_loop_poll(struct tevent_context *ev,
if (pfd->revents & POLLOUT) {
flags |= TEVENT_FD_WRITE;
}
/*
* Note that fde->flags could be changed when using
* the poll_mt backend together with threads,
* that why we need to check pfd->revents and fde->flags
*/
flags &= fde->flags;
if (flags != 0) {
DLIST_DEMOTE(ev->fd_events, fde, struct tevent_fd);
fde->handler(ev, fde, flags, fde->private_data);
break;
return 0;
}
}
for (i = 0; i < poll_ev->num_fds; i++) {
if (poll_ev->fds[i].revents & POLLNVAL) {
/*
* the socket is dead! this should never
* happen as the socket should have first been
* made readable and that should have removed
* the event, so this must be a bug or
* a race in the poll_mt usage.
*/
fde = poll_ev->fdes[i];
tevent_debug(ev, TEVENT_DEBUG_WARNING,
"POLLNVAL on dangling fd[%d] fde[%p] - disabling\n",
poll_ev->fds[i].fd, fde);
poll_ev->fdes[i] = NULL;
poll_ev->deleted = true;
if (fde != NULL) {
DLIST_REMOVE(ev->fd_events, fde);
fde->event_ctx = NULL;
}
}
}
@ -299,20 +658,68 @@ static int poll_event_loop_once(struct tevent_context *ev,
return poll_event_loop_poll(ev, &tval);
}
static int poll_event_loop_wait(struct tevent_context *ev,
const char *location)
{
struct poll_event_context *poll_ev = talloc_get_type_abort(
ev->additional_data, struct poll_event_context);
/*
* loop as long as we have events pending
*/
while (ev->fd_events ||
ev->timer_events ||
ev->immediate_events ||
ev->signal_events ||
poll_ev->fresh ||
poll_ev->disabled) {
int ret;
ret = _tevent_loop_once(ev, location);
if (ret != 0) {
tevent_debug(ev, TEVENT_DEBUG_FATAL,
"_tevent_loop_once() failed: %d - %s\n",
ret, strerror(errno));
return ret;
}
}
tevent_debug(ev, TEVENT_DEBUG_WARNING,
"poll_event_loop_wait() out of events\n");
return 0;
}
static const struct tevent_ops poll_event_ops = {
.context_init = poll_event_context_init,
.add_fd = poll_event_add_fd,
.set_fd_close_fn = tevent_common_fd_set_close_fn,
.get_fd_flags = tevent_common_fd_get_flags,
.set_fd_flags = poll_event_set_fd_flags,
.add_timer = tevent_common_add_timer,
.add_timer = tevent_common_add_timer_v2,
.schedule_immediate = tevent_common_schedule_immediate,
.add_signal = tevent_common_add_signal,
.loop_once = poll_event_loop_once,
.loop_wait = tevent_common_loop_wait,
.loop_wait = poll_event_loop_wait,
};
_PRIVATE_ bool tevent_poll_init(void)
{
return tevent_register_backend("poll", &poll_event_ops);
}
static const struct tevent_ops poll_event_mt_ops = {
.context_init = poll_event_context_init_mt,
.add_fd = poll_event_add_fd,
.set_fd_close_fn = tevent_common_fd_set_close_fn,
.get_fd_flags = tevent_common_fd_get_flags,
.set_fd_flags = poll_event_set_fd_flags,
.add_timer = tevent_common_add_timer_v2,
.schedule_immediate = poll_event_schedule_immediate,
.add_signal = tevent_common_add_signal,
.loop_once = poll_event_loop_once,
.loop_wait = poll_event_loop_wait,
};
_PRIVATE_ bool tevent_poll_mt_init(void)
{
return tevent_register_backend("poll_mt", &poll_event_mt_ops);
}

View File

@ -1,4 +1,4 @@
/*
/*
Unix SMB/CIFS implementation.
main select loop and event handling
Copyright (C) Andrew Tridgell 2003-2005
@ -47,6 +47,12 @@ static int select_event_context_init(struct tevent_context *ev)
{
struct select_event_context *select_ev;
/*
* We might be called during tevent_re_initialise()
* which means we need to free our old additional_data.
*/
TALLOC_FREE(ev->additional_data);
select_ev = talloc_zero(ev, struct select_event_context);
if (!select_ev) return -1;
select_ev->ev = ev;
@ -138,6 +144,7 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru
fd_set r_fds, w_fds;
struct tevent_fd *fde;
int selrtn;
int select_errno;
/* we maybe need to recalculate the maxfd */
if (select_ev->maxfd == EVENT_INVALID_MAXFD) {
@ -150,6 +157,10 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru
/* setup any fd events */
for (fde = select_ev->ev->fd_events; fde; fde = fde->next) {
if (fde->fd < 0 || fde->fd >= FD_SETSIZE) {
tevent_debug(select_ev->ev, TEVENT_DEBUG_FATAL,
"ERROR: EBADF fd[%d] >= %d "
"select_event_loop_once\n",
fde->fd, FD_SETSIZE);
errno = EBADF;
return -1;
}
@ -169,15 +180,16 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru
tevent_trace_point_callback(select_ev->ev, TEVENT_TRACE_BEFORE_WAIT);
selrtn = select(select_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
select_errno = errno;
tevent_trace_point_callback(select_ev->ev, TEVENT_TRACE_AFTER_WAIT);
if (selrtn == -1 && errno == EINTR &&
if (selrtn == -1 && select_errno == EINTR &&
select_ev->ev->signal_events) {
tevent_common_check_signal(select_ev->ev);
return 0;
}
if (selrtn == -1 && errno == EBADF) {
if (selrtn == -1 && select_errno == EBADF) {
/* the socket is dead! this should never
happen as the socket should have first been
made readable and that should have removed
@ -202,9 +214,14 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru
for (fde = select_ev->ev->fd_events; fde; fde = fde->next) {
uint16_t flags = 0;
if (FD_ISSET(fde->fd, &r_fds)) flags |= TEVENT_FD_READ;
if (FD_ISSET(fde->fd, &w_fds)) flags |= TEVENT_FD_WRITE;
if (FD_ISSET(fde->fd, &r_fds) && (fde->flags & TEVENT_FD_READ)) {
flags |= TEVENT_FD_READ;
}
if (FD_ISSET(fde->fd, &w_fds) && (fde->flags & TEVENT_FD_WRITE)) {
flags |= TEVENT_FD_WRITE;
}
if (flags) {
DLIST_DEMOTE(select_ev->ev->fd_events, fde, struct tevent_fd);
fde->handler(select_ev->ev, fde, flags, fde->private_data);
break;
}
@ -215,12 +232,12 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru
}
/*
do a single event loop using the events defined in ev
do a single event loop using the events defined in ev
*/
static int select_event_loop_once(struct tevent_context *ev, const char *location)
{
struct select_event_context *select_ev = talloc_get_type(ev->additional_data,
struct select_event_context);
struct select_event_context);
struct timeval tval;
if (ev->signal_events &&
@ -247,7 +264,7 @@ static const struct tevent_ops select_event_ops = {
.set_fd_close_fn = tevent_common_fd_set_close_fn,
.get_fd_flags = tevent_common_fd_get_flags,
.set_fd_flags = tevent_common_fd_set_flags,
.add_timer = tevent_common_add_timer,
.add_timer = tevent_common_add_timer_v2,
.schedule_immediate = tevent_common_schedule_immediate,
.add_signal = tevent_common_add_signal,
.loop_once = select_event_loop_once,

View File

@ -1,4 +1,4 @@
/*
/*
Unix SMB/CIFS implementation.
common events code for signal events
@ -30,8 +30,6 @@
#include "tevent_internal.h"
#include "tevent_util.h"
#define TEVENT_NUM_SIGNALS 64
/* maximum number of SA_SIGINFO signals to hold in the queue.
NB. This *MUST* be a power of 2, in order for the ring buffer
wrap to work correctly. Thanks to Petr Vandrovec <petr@vandrovec.name>
@ -121,10 +119,39 @@ static void tevent_common_signal_handler_info(int signum, siginfo_t *info,
if (count+1 == TEVENT_SA_INFO_QUEUE_COUNT) {
/* we've filled the info array - block this signal until
these ones are delivered */
#ifdef HAVE_UCONTEXT_T
/*
* This is the only way for this to work.
* By default signum is blocked inside this
* signal handler using a temporary mask,
* but what we really need to do now is
* block it in the callers mask, so it
* stays blocked when the temporary signal
* handler mask is replaced when we return
* from here. The callers mask can be found
* in the ucontext_t passed in as the
* void *uctx argument.
*/
ucontext_t *ucp = (ucontext_t *)uctx;
sigaddset(&ucp->uc_sigmask, signum);
#else
/*
* WARNING !!! WARNING !!!!
*
* This code doesn't work.
* By default signum is blocked inside this
* signal handler, but calling sigprocmask
* modifies the temporary signal mask being
* used *inside* this handler, which will be
* replaced by the callers signal mask once
* we return from here. See Samba
* bug #9550 for details.
*/
sigset_t set;
sigemptyset(&set);
sigaddset(&set, signum);
sigprocmask(SIG_BLOCK, &set, NULL);
#endif
TEVENT_SIG_INCREMENT(sig_state->sig_blocked[signum]);
}
}
@ -175,7 +202,7 @@ static int tevent_signal_destructor(struct tevent_signal *se)
/*
this is part of the pipe hack needed to avoid the signal race condition
*/
static void signal_pipe_handler(struct tevent_context *ev, struct tevent_fd *fde,
static void signal_pipe_handler(struct tevent_context *ev, struct tevent_fd *fde,
uint16_t flags, void *_private)
{
char c[16];
@ -284,7 +311,7 @@ struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
sig_state->oldact[signum] = talloc(sig_state, struct sigaction);
if (sig_state->oldact[signum] == NULL) {
talloc_free(se);
return NULL;
return NULL;
}
if (sigaction(signum, &act, sig_state->oldact[signum]) == -1) {
talloc_free(se);
@ -328,7 +355,7 @@ int tevent_common_check_signal(struct tevent_context *ev)
if (!sig_state || !TEVENT_SIG_PENDING(sig_state->got_signal)) {
return 0;
}
for (i=0;i<TEVENT_NUM_SIGNALS+1;i++) {
struct tevent_common_signal_list *sl, *next;
struct tevent_sigcounter counter = sig_state->signal_count[i];
@ -377,7 +404,7 @@ int tevent_common_check_signal(struct tevent_context *ev)
uint32_t ofs = (counter.seen + j)
% TEVENT_SA_INFO_QUEUE_COUNT;
se->handler(ev, se, i, 1,
(void*)&sig_state->sig_info[i][ofs],
(void*)&sig_state->sig_info[i][ofs],
se->private_data);
if (!exists) {
break;

View File

@ -1,8 +1,8 @@
/*
/*
Unix SMB/CIFS implementation.
main select loop and event handling
Copyright (C) Andrew Tridgell 2003-2005
Copyright (C) Stefan Metzmacher 2005-2009
Copyright (C) Stefan Metzmacher 2013
Copyright (C) Jeremy Allison 2013
** NOTE! The following LGPL license applies to the tevent
** library. This does NOT imply that all of Samba is released
@ -26,565 +26,207 @@
This is SAMBA's default event loop code
- we try to use epoll if configure detected support for it
otherwise we use select()
otherwise we use poll()
- if epoll is broken on the system or the kernel doesn't support it
at runtime we fallback to select()
at runtime we fallback to poll()
*/
#include "replace.h"
#include "system/filesys.h"
#include "system/select.h"
#include "tevent.h"
#include "tevent_util.h"
#include "tevent_internal.h"
struct std_event_context {
/* a pointer back to the generic event_context */
struct tevent_context *ev;
/* the maximum file descriptor number in fd_events */
int maxfd;
/* information for exiting from the event loop */
int exit_code;
/* when using epoll this is the handle from epoll_create */
int epoll_fd;
/* our pid at the time the epoll_fd was created */
pid_t pid;
struct std_event_glue {
const struct tevent_ops *epoll_ops;
const struct tevent_ops *poll_ops;
struct tevent_ops *glue_ops;
bool fallback_replay;
};
static int std_event_context_init(struct tevent_context *ev);
static const struct tevent_ops std_event_ops = {
.context_init = std_event_context_init,
};
/* use epoll if it is available */
#if HAVE_EPOLL
/*
called when a epoll call fails, and we should fallback
to using select
If this function gets called. epoll failed at runtime.
Move us to using poll instead. If we return false here,
caller should abort().
*/
static void epoll_fallback_to_select(struct std_event_context *std_ev, const char *reason)
{
tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
"%s (%s) - falling back to select()\n",
reason, strerror(errno));
close(std_ev->epoll_fd);
std_ev->epoll_fd = -1;
talloc_set_destructor(std_ev, NULL);
}
/*
map from TEVENT_FD_* to EPOLLIN/EPOLLOUT
*/
static uint32_t epoll_map_flags(uint16_t flags)
{
uint32_t ret = 0;
if (flags & TEVENT_FD_READ) ret |= (EPOLLIN | EPOLLERR | EPOLLHUP);
if (flags & TEVENT_FD_WRITE) ret |= (EPOLLOUT | EPOLLERR | EPOLLHUP);
return ret;
}
/*
free the epoll fd
*/
static int epoll_ctx_destructor(struct std_event_context *std_ev)
{
if (std_ev->epoll_fd != -1) {
close(std_ev->epoll_fd);
}
std_ev->epoll_fd = -1;
return 0;
}
/*
init the epoll fd
*/
static void epoll_init_ctx(struct std_event_context *std_ev)
{
std_ev->epoll_fd = epoll_create(64);
if (std_ev->epoll_fd == -1) {
tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
"Failed to create epoll handle.\n");
return;
}
if (!ev_set_close_on_exec(std_ev->epoll_fd)) {
tevent_debug(std_ev->ev, TEVENT_DEBUG_WARNING,
"Failed to set close-on-exec, file descriptor may be leaked to children.\n");
}
std_ev->pid = getpid();
talloc_set_destructor(std_ev, epoll_ctx_destructor);
}
static void epoll_add_event(struct std_event_context *std_ev, struct tevent_fd *fde);
/*
reopen the epoll handle when our pid changes
see http://junkcode.samba.org/ftp/unpacked/junkcode/epoll_fork.c for an
demonstration of why this is needed
*/
static void epoll_check_reopen(struct std_event_context *std_ev)
static bool std_fallback_to_poll(struct tevent_context *ev, bool replay)
{
void *glue_ptr = talloc_parent(ev->ops);
struct std_event_glue *glue =
talloc_get_type_abort(glue_ptr,
struct std_event_glue);
int ret;
struct tevent_fd *fde;
struct tevent_fd *fde_next;
if (std_ev->pid == getpid()) {
return;
glue->fallback_replay = replay;
/* First switch all the ops to poll. */
glue->epoll_ops = NULL;
/*
* Set custom_ops the same as poll.
*/
*glue->glue_ops = *glue->poll_ops;
glue->glue_ops->context_init = std_event_context_init;
/* Next initialize the poll backend. */
ret = glue->poll_ops->context_init(ev);
if (ret != 0) {
return false;
}
close(std_ev->epoll_fd);
std_ev->epoll_fd = epoll_create(64);
if (std_ev->epoll_fd == -1) {
tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
"Failed to recreate epoll handle after fork\n");
return;
}
if (!ev_set_close_on_exec(std_ev->epoll_fd)) {
tevent_debug(std_ev->ev, TEVENT_DEBUG_WARNING,
"Failed to set close-on-exec, file descriptor may be leaked to children.\n");
}
std_ev->pid = getpid();
for (fde=std_ev->ev->fd_events;fde;fde=fde->next) {
epoll_add_event(std_ev, fde);
}
}
#define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT (1<<0)
#define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1)
#define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2)
/*
add the epoll event to the given fd_event
*/
static void epoll_add_event(struct std_event_context *std_ev, struct tevent_fd *fde)
{
struct epoll_event event;
if (std_ev->epoll_fd == -1) return;
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
/* if we don't want events yet, don't add an epoll_event */
if (fde->flags == 0) return;
ZERO_STRUCT(event);
event.events = epoll_map_flags(fde->flags);
event.data.ptr = fde;
if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event) != 0) {
epoll_fallback_to_select(std_ev, "EPOLL_CTL_ADD failed");
}
fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
/* only if we want to read we want to tell the event handler about errors */
if (fde->flags & TEVENT_FD_READ) {
fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
}
}
/*
delete the epoll event for given fd_event
*/
static void epoll_del_event(struct std_event_context *std_ev, struct tevent_fd *fde)
{
struct epoll_event event;
if (std_ev->epoll_fd == -1) return;
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
/* if there's no epoll_event, we don't need to delete it */
if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT)) return;
ZERO_STRUCT(event);
event.events = epoll_map_flags(fde->flags);
event.data.ptr = fde;
epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event);
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
}
/*
change the epoll event to the given fd_event
*/
static void epoll_mod_event(struct std_event_context *std_ev, struct tevent_fd *fde)
{
struct epoll_event event;
if (std_ev->epoll_fd == -1) return;
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
ZERO_STRUCT(event);
event.events = epoll_map_flags(fde->flags);
event.data.ptr = fde;
if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) {
epoll_fallback_to_select(std_ev, "EPOLL_CTL_MOD failed");
}
/* only if we want to read we want to tell the event handler about errors */
if (fde->flags & TEVENT_FD_READ) {
fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
}
}
static void epoll_change_event(struct std_event_context *std_ev, struct tevent_fd *fde)
{
bool got_error = (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR);
bool want_read = (fde->flags & TEVENT_FD_READ);
bool want_write= (fde->flags & TEVENT_FD_WRITE);
if (std_ev->epoll_fd == -1) return;
fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR;
/* there's already an event */
if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT) {
if (want_read || (want_write && !got_error)) {
epoll_mod_event(std_ev, fde);
return;
}
/*
* Now we have to change all the existing file descriptor
* events from the epoll backend to the poll backend.
*/
for (fde = ev->fd_events; fde; fde = fde_next) {
/*
* if we want to match the select behavior, we need to remove the epoll_event
* when the caller isn't interested in events.
*
* this is because epoll reports EPOLLERR and EPOLLHUP, even without asking for them
* We must remove this fde off the ev->fd_events list.
*/
epoll_del_event(std_ev, fde);
return;
fde_next = fde->next;
/* Remove from the ev->fd_events list. */
DLIST_REMOVE(ev->fd_events, fde);
/* Re-add this event as a poll backend event. */
tevent_poll_event_add_fd_internal(ev, fde);
}
/* there's no epoll_event attached to the fde */
if (want_read || (want_write && !got_error)) {
epoll_add_event(std_ev, fde);
return;
}
return true;
}
/*
event loop handling using epoll
*/
static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tvalp)
static int std_event_loop_once(struct tevent_context *ev, const char *location)
{
int ret, i;
#define MAXEVENTS 1
struct epoll_event events[MAXEVENTS];
int timeout = -1;
void *glue_ptr = talloc_parent(ev->ops);
struct std_event_glue *glue =
talloc_get_type_abort(glue_ptr,
struct std_event_glue);
int ret;
if (std_ev->epoll_fd == -1) return -1;
if (tvalp) {
/* it's better to trigger timed events a bit later than to early */
timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
ret = glue->epoll_ops->loop_once(ev, location);
if (glue->epoll_ops != NULL) {
/* No fallback */
return ret;
}
if (std_ev->ev->signal_events &&
tevent_common_check_signal(std_ev->ev)) {
return 0;
if (!glue->fallback_replay) {
/*
* The problem happened while modifying an event.
* An event handler was triggered in this case
* and there is no need to call loop_once() again.
*/
return ret;
}
tevent_trace_point_callback(std_ev->ev, TEVENT_TRACE_BEFORE_WAIT);
ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout);
tevent_trace_point_callback(std_ev->ev, TEVENT_TRACE_AFTER_WAIT);
if (ret == -1 && errno == EINTR && std_ev->ev->signal_events) {
if (tevent_common_check_signal(std_ev->ev)) {
return 0;
}
}
if (ret == -1 && errno != EINTR) {
epoll_fallback_to_select(std_ev, "epoll_wait() failed");
return -1;
}
if (ret == 0 && tvalp) {
/* we don't care about a possible delay here */
tevent_common_loop_timer_delay(std_ev->ev);
return 0;
}
for (i=0;i<ret;i++) {
struct tevent_fd *fde = talloc_get_type(events[i].data.ptr,
struct tevent_fd);
uint16_t flags = 0;
if (fde == NULL) {
epoll_fallback_to_select(std_ev, "epoll_wait() gave bad data");
return -1;
}
if (events[i].events & (EPOLLHUP|EPOLLERR)) {
fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR;
/*
* if we only wait for TEVENT_FD_WRITE, we should not tell the
* event handler about it, and remove the epoll_event,
* as we only report errors when waiting for read events,
* to match the select() behavior
*/
if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) {
epoll_del_event(std_ev, fde);
continue;
}
flags |= TEVENT_FD_READ;
}
if (events[i].events & EPOLLIN) flags |= TEVENT_FD_READ;
if (events[i].events & EPOLLOUT) flags |= TEVENT_FD_WRITE;
if (flags) {
fde->handler(std_ev->ev, fde, flags, fde->private_data);
break;
}
}
return 0;
return glue->poll_ops->loop_once(ev, location);
}
#else
#define epoll_init_ctx(std_ev)
#define epoll_add_event(std_ev,fde)
#define epoll_del_event(std_ev,fde)
#define epoll_change_event(std_ev,fde)
#define epoll_event_loop(std_ev,tvalp) (-1)
#define epoll_check_reopen(std_ev)
#endif
static int std_event_loop_wait(struct tevent_context *ev, const char *location)
{
void *glue_ptr = talloc_parent(ev->ops);
struct std_event_glue *glue =
talloc_get_type_abort(glue_ptr,
struct std_event_glue);
int ret;
ret = glue->epoll_ops->loop_wait(ev, location);
if (glue->epoll_ops != NULL) {
/* No fallback */
return ret;
}
return glue->poll_ops->loop_wait(ev, location);
}
/*
create a std_event_context structure.
Initialize the epoll backend and allow it to call a
switch function if epoll fails at runtime.
*/
static int std_event_context_init(struct tevent_context *ev)
{
struct std_event_context *std_ev;
struct std_event_glue *glue;
int ret;
std_ev = talloc_zero(ev, struct std_event_context);
if (!std_ev) return -1;
std_ev->ev = ev;
std_ev->epoll_fd = -1;
/*
* If this is the first initialization
* we need to set up the allocated ops
* pointers.
*/
epoll_init_ctx(std_ev);
ev->additional_data = std_ev;
return 0;
}
/*
recalculate the maxfd
*/
static void calc_maxfd(struct std_event_context *std_ev)
{
struct tevent_fd *fde;
std_ev->maxfd = 0;
for (fde = std_ev->ev->fd_events; fde; fde = fde->next) {
if (fde->fd > std_ev->maxfd) {
std_ev->maxfd = fde->fd;
}
}
}
/* to mark the ev->maxfd invalid
* this means we need to recalculate it
*/
#define EVENT_INVALID_MAXFD (-1)
/*
destroy an fd_event
*/
static int std_event_fd_destructor(struct tevent_fd *fde)
{
struct tevent_context *ev = fde->event_ctx;
struct std_event_context *std_ev = NULL;
if (ev) {
std_ev = talloc_get_type(ev->additional_data,
struct std_event_context);
epoll_check_reopen(std_ev);
if (std_ev->maxfd == fde->fd) {
std_ev->maxfd = EVENT_INVALID_MAXFD;
}
epoll_del_event(std_ev, fde);
}
return tevent_common_fd_destructor(fde);
}
/*
add a fd based event
return NULL on failure (memory allocation error)
*/
static struct tevent_fd *std_event_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx,
int fd, uint16_t flags,
tevent_fd_handler_t handler,
void *private_data,
const char *handler_name,
const char *location)
{
struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
struct std_event_context);
struct tevent_fd *fde;
epoll_check_reopen(std_ev);
fde = tevent_common_add_fd(ev, mem_ctx, fd, flags,
handler, private_data,
handler_name, location);
if (!fde) return NULL;
if ((std_ev->maxfd != EVENT_INVALID_MAXFD)
&& (fde->fd > std_ev->maxfd)) {
std_ev->maxfd = fde->fd;
}
talloc_set_destructor(fde, std_event_fd_destructor);
epoll_add_event(std_ev, fde);
return fde;
}
/*
set the fd event flags
*/
static void std_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
{
struct tevent_context *ev;
struct std_event_context *std_ev;
if (fde->flags == flags) return;
ev = fde->event_ctx;
std_ev = talloc_get_type(ev->additional_data, struct std_event_context);
fde->flags = flags;
epoll_check_reopen(std_ev);
epoll_change_event(std_ev, fde);
}
/*
event loop handling using select()
*/
static int std_event_loop_select(struct std_event_context *std_ev, struct timeval *tvalp)
{
fd_set r_fds, w_fds;
struct tevent_fd *fde;
int selrtn;
/* we maybe need to recalculate the maxfd */
if (std_ev->maxfd == EVENT_INVALID_MAXFD) {
calc_maxfd(std_ev);
}
FD_ZERO(&r_fds);
FD_ZERO(&w_fds);
/* setup any fd events */
for (fde = std_ev->ev->fd_events; fde; fde = fde->next) {
if (fde->fd < 0 || fde->fd >= FD_SETSIZE) {
std_ev->exit_code = EBADF;
if (ev->ops == &std_event_ops) {
glue = talloc_zero(ev, struct std_event_glue);
if (glue == NULL) {
return -1;
}
if (fde->flags & TEVENT_FD_READ) {
FD_SET(fde->fd, &r_fds);
glue->epoll_ops = tevent_find_ops_byname("epoll");
glue->poll_ops = tevent_find_ops_byname("poll");
if (glue->poll_ops == NULL) {
return -1;
}
if (fde->flags & TEVENT_FD_WRITE) {
FD_SET(fde->fd, &w_fds);
/*
* Allocate space for our custom ops.
* Allocate as a child of our epoll_ops pointer
* so we can easily get to it using talloc_parent.
*/
glue->glue_ops = talloc_zero(glue, struct tevent_ops);
if (glue->glue_ops == NULL) {
talloc_free(glue);
return -1;
}
ev->ops = glue->glue_ops;
} else {
void *glue_ptr = talloc_parent(ev->ops);
glue = talloc_get_type_abort(glue_ptr, struct std_event_glue);
}
if (std_ev->ev->signal_events &&
tevent_common_check_signal(std_ev->ev)) {
return 0;
}
if (glue->epoll_ops != NULL) {
/*
* Set custom_ops the same as epoll,
* except re-init using std_event_context_init()
* and use std_event_loop_once() to add the
* ability to fallback to a poll backend on
* epoll runtime error.
*/
*glue->glue_ops = *glue->epoll_ops;
glue->glue_ops->context_init = std_event_context_init;
glue->glue_ops->loop_once = std_event_loop_once;
glue->glue_ops->loop_wait = std_event_loop_wait;
selrtn = select(std_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
if (selrtn == -1 && errno == EINTR &&
std_ev->ev->signal_events) {
tevent_common_check_signal(std_ev->ev);
return 0;
}
if (selrtn == -1 && errno == EBADF) {
/* the socket is dead! this should never
happen as the socket should have first been
made readable and that should have removed
the event, so this must be a bug. This is a
fatal error. */
tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
"ERROR: EBADF on std_event_loop_once\n");
std_ev->exit_code = EBADF;
return -1;
}
if (selrtn == 0 && tvalp) {
/* we don't care about a possible delay here */
tevent_common_loop_timer_delay(std_ev->ev);
return 0;
}
if (selrtn > 0) {
/* at least one file descriptor is ready - check
which ones and call the handler, being careful to allow
the handler to remove itself when called */
for (fde = std_ev->ev->fd_events; fde; fde = fde->next) {
uint16_t flags = 0;
if (FD_ISSET(fde->fd, &r_fds)) flags |= TEVENT_FD_READ;
if (FD_ISSET(fde->fd, &w_fds)) flags |= TEVENT_FD_WRITE;
if (flags & fde->flags) {
fde->handler(std_ev->ev, fde, flags, fde->private_data);
break;
}
ret = glue->epoll_ops->context_init(ev);
if (ret == -1) {
goto fallback;
}
#ifdef HAVE_EPOLL
if (!tevent_epoll_set_panic_fallback(ev, std_fallback_to_poll)) {
TALLOC_FREE(ev->additional_data);
goto fallback;
}
#endif
return ret;
}
return 0;
fallback:
glue->epoll_ops = NULL;
/*
* Set custom_ops the same as poll.
*/
*glue->glue_ops = *glue->poll_ops;
glue->glue_ops->context_init = std_event_context_init;
return glue->poll_ops->context_init(ev);
}
/*
do a single event loop using the events defined in ev
*/
static int std_event_loop_once(struct tevent_context *ev, const char *location)
{
struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
struct std_event_context);
struct timeval tval;
if (ev->signal_events &&
tevent_common_check_signal(ev)) {
return 0;
}
if (ev->immediate_events &&
tevent_common_loop_immediate(ev)) {
return 0;
}
tval = tevent_common_loop_timer_delay(ev);
if (tevent_timeval_is_zero(&tval)) {
return 0;
}
epoll_check_reopen(std_ev);
if (epoll_event_loop(std_ev, &tval) == 0) {
return 0;
}
return std_event_loop_select(std_ev, &tval);
}
static const struct tevent_ops std_event_ops = {
.context_init = std_event_context_init,
.add_fd = std_event_add_fd,
.set_fd_close_fn = tevent_common_fd_set_close_fn,
.get_fd_flags = tevent_common_fd_get_flags,
.set_fd_flags = std_event_set_fd_flags,
.add_timer = tevent_common_add_timer,
.schedule_immediate = tevent_common_schedule_immediate,
.add_signal = tevent_common_add_signal,
.loop_once = std_event_loop_once,
.loop_wait = tevent_common_loop_wait,
};
_PRIVATE_ bool tevent_standard_init(void)
{
return tevent_register_backend("standard", &std_event_ops);

View File

@ -1,4 +1,4 @@
/*
/*
Unix SMB/CIFS implementation.
common events code for timed events
@ -31,7 +31,7 @@
#include "tevent_util.h"
/**
compare two timeval structures.
compare two timeval structures.
Return -1 if tv1 < tv2
Return 0 if tv1 == tv2
Return 1 if tv1 > tv2
@ -133,13 +133,18 @@ struct timeval tevent_timeval_current_ofs(uint32_t secs, uint32_t usecs)
*/
static int tevent_common_timed_destructor(struct tevent_timer *te)
{
if (te->event_ctx == NULL) {
return 0;
}
tevent_debug(te->event_ctx, TEVENT_DEBUG_TRACE,
"Destroying timer event %p \"%s\"\n",
te, te->handler_name);
if (te->event_ctx) {
DLIST_REMOVE(te->event_ctx->timer_events, te);
if (te->event_ctx->last_zero_timer == te) {
te->event_ctx->last_zero_timer = DLIST_PREV(te);
}
DLIST_REMOVE(te->event_ctx->timer_events, te);
return 0;
}
@ -153,14 +158,17 @@ static int tevent_common_timed_deny_destructor(struct tevent_timer *te)
add a timed event
return NULL on failure (memory allocation error)
*/
struct tevent_timer *tevent_common_add_timer(struct tevent_context *ev, TALLOC_CTX *mem_ctx,
struct timeval next_event,
tevent_timer_handler_t handler,
void *private_data,
const char *handler_name,
const char *location)
static struct tevent_timer *tevent_common_add_timer_internal(
struct tevent_context *ev,
TALLOC_CTX *mem_ctx,
struct timeval next_event,
tevent_timer_handler_t handler,
void *private_data,
const char *handler_name,
const char *location,
bool optimize_zero)
{
struct tevent_timer *te, *last_te, *cur_te;
struct tevent_timer *te, *prev_te, *cur_te;
te = talloc(mem_ctx?mem_ctx:ev, struct tevent_timer);
if (te == NULL) return NULL;
@ -173,18 +181,52 @@ struct tevent_timer *tevent_common_add_timer(struct tevent_context *ev, TALLOC_C
te->location = location;
te->additional_data = NULL;
if (ev->timer_events == NULL) {
ev->last_zero_timer = NULL;
}
/* keep the list ordered */
last_te = NULL;
for (cur_te = ev->timer_events; cur_te; cur_te = cur_te->next) {
/* if the new event comes before the current one break */
if (tevent_timeval_compare(&te->next_event, &cur_te->next_event) < 0) {
prev_te = NULL;
if (optimize_zero && tevent_timeval_is_zero(&te->next_event)) {
/*
* Some callers use zero tevent_timer
* instead of tevent_immediate events.
*
* As these can happen very often,
* we remember the last zero timer
* in the list.
*/
prev_te = ev->last_zero_timer;
ev->last_zero_timer = te;
} else {
/*
* we traverse the list from the tail
* because it's much more likely that
* timers are added at the end of the list
*/
for (cur_te = DLIST_TAIL(ev->timer_events);
cur_te != NULL;
cur_te = DLIST_PREV(cur_te))
{
int ret;
/*
* if the new event comes before the current
* we continue searching
*/
ret = tevent_timeval_compare(&te->next_event,
&cur_te->next_event);
if (ret < 0) {
continue;
}
break;
}
last_te = cur_te;
prev_te = cur_te;
}
DLIST_ADD_AFTER(ev->timer_events, te, last_te);
DLIST_ADD_AFTER(ev->timer_events, te, prev_te);
talloc_set_destructor(te, tevent_common_timed_destructor);
@ -194,6 +236,44 @@ struct tevent_timer *tevent_common_add_timer(struct tevent_context *ev, TALLOC_C
return te;
}
struct tevent_timer *tevent_common_add_timer(struct tevent_context *ev,
TALLOC_CTX *mem_ctx,
struct timeval next_event,
tevent_timer_handler_t handler,
void *private_data,
const char *handler_name,
const char *location)
{
/*
* do not use optimization, there are broken Samba
* versions which use tevent_common_add_timer()
* without using tevent_common_loop_timer_delay(),
* it just uses DLIST_REMOVE(ev->timer_events, te)
* and would leave ev->last_zero_timer behind.
*/
return tevent_common_add_timer_internal(ev, mem_ctx, next_event,
handler, private_data,
handler_name, location,
false);
}
struct tevent_timer *tevent_common_add_timer_v2(struct tevent_context *ev,
TALLOC_CTX *mem_ctx,
struct timeval next_event,
tevent_timer_handler_t handler,
void *private_data,
const char *handler_name,
const char *location)
{
/*
* Here we turn on last_zero_timer optimization
*/
return tevent_common_add_timer_internal(ev, mem_ctx, next_event,
handler, private_data,
handler_name, location,
true);
}
/*
do a single event loop using the events defined in ev
@ -242,8 +322,15 @@ struct timeval tevent_common_loop_timer_delay(struct tevent_context *ev)
/* We need to remove the timer from the list before calling the
* handler because in a semi-async inner event loop called from the
* handler we don't want to come across this event again -- vl */
if (ev->last_zero_timer == te) {
ev->last_zero_timer = DLIST_PREV(te);
}
DLIST_REMOVE(ev->timer_events, te);
tevent_debug(te->event_ctx, TEVENT_DEBUG_TRACE,
"Running timer event %p \"%s\"\n",
te, te->handler_name);
/*
* If the timed event was registered for a zero current_time,
* then we pass a zero timeval here too! To avoid the
@ -265,3 +352,4 @@ struct timeval tevent_common_loop_timer_delay(struct tevent_context *ev)
return tevent_timeval_zero();
}

View File

@ -67,3 +67,4 @@ bool tevent_wakeup_recv(struct tevent_req *req)
return false;
}

138
ctdb/lib/tevent/wscript Executable file
View File

@ -0,0 +1,138 @@
#!/usr/bin/env python
APPNAME = 'tevent'
VERSION = '0.9.18'
blddir = 'bin'
import sys, os
# find the buildtools directory
srcdir = '.'
while not os.path.exists(srcdir+'/buildtools') and len(srcdir.split('/')) < 5:
srcdir = '../' + srcdir
sys.path.insert(0, srcdir + '/buildtools/wafsamba')
import wafsamba, samba_dist, Options, Logs
samba_dist.DIST_DIRS('lib/tevent:. lib/replace:lib/replace lib/talloc:lib/talloc buildtools:buildtools')
def set_options(opt):
opt.BUILTIN_DEFAULT('replace')
opt.PRIVATE_EXTENSION_DEFAULT('tevent', noextension='tevent')
opt.RECURSE('lib/replace')
opt.RECURSE('lib/talloc')
if opt.IN_LAUNCH_DIR():
opt.add_option('--disable-python',
help=("disable the pytevent module"),
action="store_true", dest='disable_python', default=False)
def configure(conf):
conf.RECURSE('lib/replace')
conf.RECURSE('lib/talloc')
conf.env.standalone_tevent = conf.IN_LAUNCH_DIR()
if not conf.env.standalone_tevent:
if conf.CHECK_BUNDLED_SYSTEM_PKG('tevent', minversion=VERSION,
onlyif='talloc', implied_deps='replace talloc'):
conf.define('USING_SYSTEM_TEVENT', 1)
if conf.CHECK_BUNDLED_SYSTEM_PYTHON('pytevent', 'tevent', minversion=VERSION):
conf.define('USING_SYSTEM_PYTEVENT', 1)
if conf.CHECK_FUNCS('epoll_create', headers='sys/epoll.h'):
conf.DEFINE('HAVE_EPOLL', 1)
tevent_num_signals = 64
v = conf.CHECK_VALUEOF('NSIG', headers='signal.h')
if v is not None:
tevent_num_signals = max(tevent_num_signals, v)
v = conf.CHECK_VALUEOF('_NSIG', headers='signal.h')
if v is not None:
tevent_num_signals = max(tevent_num_signals, v)
v = conf.CHECK_VALUEOF('SIGRTMAX', headers='signal.h')
if v is not None:
tevent_num_signals = max(tevent_num_signals, v)
v = conf.CHECK_VALUEOF('SIGRTMIN', headers='signal.h')
if v is not None:
tevent_num_signals = max(tevent_num_signals, v*2)
if not conf.CONFIG_SET('USING_SYSTEM_TEVENT'):
conf.DEFINE('TEVENT_NUM_SIGNALS', tevent_num_signals)
conf.env.disable_python = getattr(Options.options, 'disable_python', False)
if not conf.env.disable_python:
# also disable if we don't have the python libs installed
conf.find_program('python', var='PYTHON')
conf.check_tool('python')
conf.check_python_version((2,4,2))
conf.SAMBA_CHECK_PYTHON_HEADERS(mandatory=False)
if not conf.env.HAVE_PYTHON_H:
Logs.warn('Disabling pytevent as python devel libs not found')
conf.env.disable_python = True
conf.SAMBA_CONFIG_H()
conf.SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS()
def build(bld):
bld.RECURSE('lib/replace')
bld.RECURSE('lib/talloc')
SRC = '''tevent.c tevent_debug.c tevent_fd.c tevent_immediate.c
tevent_queue.c tevent_req.c tevent_select.c
tevent_poll.c
tevent_signal.c tevent_standard.c tevent_timed.c tevent_util.c tevent_wakeup.c'''
if bld.CONFIG_SET('HAVE_EPOLL'):
SRC += ' tevent_epoll.c'
if bld.env.standalone_tevent:
bld.env.PKGCONFIGDIR = '${LIBDIR}/pkgconfig'
private_library = False
else:
private_library = True
if not bld.CONFIG_SET('USING_SYSTEM_TEVENT'):
bld.SAMBA_LIBRARY('tevent',
SRC,
deps='replace talloc',
enabled= not bld.CONFIG_SET('USING_SYSTEM_TEVENT'),
includes='.',
abi_directory='ABI',
abi_match='tevent_* _tevent_*',
vnum=VERSION,
public_headers='tevent.h',
public_headers_install=not private_library,
pc_files='tevent.pc',
private_library=private_library)
if not bld.CONFIG_SET('USING_SYSTEM_PYTEVENT') and not bld.env.disable_python:
bld.SAMBA_PYTHON('pytevent',
'pytevent.c',
deps='tevent',
realname='_tevent.so',
cflags='-DPACKAGE_VERSION=\"%s\"' % VERSION)
# install out various python scripts for use by make test
bld.SAMBA_SCRIPT('tevent_python',
pattern='tevent.py',
installdir='python')
bld.INSTALL_WILDCARD('${PYTHONARCHDIR}', 'tevent.py', flat=False)
def test(ctx):
'''test tevent'''
print("The tevent testsuite is part of smbtorture in samba4")
def dist():
'''makes a tarball for distribution'''
samba_dist.dist()
def reconfigure(ctx):
'''reconfigure if config scripts have changed'''
import samba_utils
samba_utils.reconfigure(ctx)