diff options
Diffstat (limited to 'lib/tevent')
82 files changed, 24519 insertions, 0 deletions
diff --git a/lib/tevent/ABI/tevent-0.10.0.sigs b/lib/tevent/ABI/tevent-0.10.0.sigs new file mode 100644 index 0000000..f6227db --- /dev/null +++ b/lib/tevent/ABI/tevent-0.10.0.sigs @@ -0,0 +1,126 @@ +_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_context_pop_use: void (struct tevent_context *, const char *) +_tevent_context_push_use: bool (struct tevent_context *, const char *) +_tevent_context_wrapper_create: struct tevent_context *(struct tevent_context *, TALLOC_CTX *, const struct tevent_wrapper_ops *, void *, size_t, 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_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_abort: void (struct tevent_context *, 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_double_free: void (TALLOC_CTX *, 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_have_events: bool (struct tevent_context *) +tevent_common_invoke_fd_handler: int (struct tevent_fd *, uint16_t, bool *) +tevent_common_invoke_immediate_handler: int (struct tevent_immediate *, bool *) +tevent_common_invoke_signal_handler: int (struct tevent_signal *, int, int, void *, bool *) +tevent_common_invoke_timer_handler: int (struct tevent_timer *, struct timeval, bool *) +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_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +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_context_is_wrapper: bool (struct tevent_context *) +tevent_context_same_loop: bool (struct tevent_context *, struct tevent_context *) +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_num_signals: size_t (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_entry_untrigger: void (struct tevent_queue_entry *) +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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_get_profile: const struct tevent_req_profile *(struct tevent_req *) +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_move_profile: struct tevent_req_profile *(struct tevent_req *, TALLOC_CTX *) +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_profile_append_sub: void (struct tevent_req_profile *, struct tevent_req_profile **) +tevent_req_profile_create: struct tevent_req_profile *(TALLOC_CTX *) +tevent_req_profile_get_name: void (const struct tevent_req_profile *, const char **) +tevent_req_profile_get_start: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_status: void (const struct tevent_req_profile *, pid_t *, enum tevent_req_state *, uint64_t *) +tevent_req_profile_get_stop: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_subprofiles: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_next: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_set_name: bool (struct tevent_req_profile *, const char *) +tevent_req_profile_set_start: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_profile_set_status: void (struct tevent_req_profile *, pid_t, enum tevent_req_state, uint64_t) +tevent_req_profile_set_stop: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_received: void (struct tevent_req *) +tevent_req_reset_endtime: 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_req_set_profile: bool (struct tevent_req *) +tevent_sa_info_queue_count: size_t (void) +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_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, 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_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/ABI/tevent-0.10.1.sigs b/lib/tevent/ABI/tevent-0.10.1.sigs new file mode 100644 index 0000000..f6227db --- /dev/null +++ b/lib/tevent/ABI/tevent-0.10.1.sigs @@ -0,0 +1,126 @@ +_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_context_pop_use: void (struct tevent_context *, const char *) +_tevent_context_push_use: bool (struct tevent_context *, const char *) +_tevent_context_wrapper_create: struct tevent_context *(struct tevent_context *, TALLOC_CTX *, const struct tevent_wrapper_ops *, void *, size_t, 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_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_abort: void (struct tevent_context *, 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_double_free: void (TALLOC_CTX *, 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_have_events: bool (struct tevent_context *) +tevent_common_invoke_fd_handler: int (struct tevent_fd *, uint16_t, bool *) +tevent_common_invoke_immediate_handler: int (struct tevent_immediate *, bool *) +tevent_common_invoke_signal_handler: int (struct tevent_signal *, int, int, void *, bool *) +tevent_common_invoke_timer_handler: int (struct tevent_timer *, struct timeval, bool *) +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_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +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_context_is_wrapper: bool (struct tevent_context *) +tevent_context_same_loop: bool (struct tevent_context *, struct tevent_context *) +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_num_signals: size_t (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_entry_untrigger: void (struct tevent_queue_entry *) +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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_get_profile: const struct tevent_req_profile *(struct tevent_req *) +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_move_profile: struct tevent_req_profile *(struct tevent_req *, TALLOC_CTX *) +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_profile_append_sub: void (struct tevent_req_profile *, struct tevent_req_profile **) +tevent_req_profile_create: struct tevent_req_profile *(TALLOC_CTX *) +tevent_req_profile_get_name: void (const struct tevent_req_profile *, const char **) +tevent_req_profile_get_start: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_status: void (const struct tevent_req_profile *, pid_t *, enum tevent_req_state *, uint64_t *) +tevent_req_profile_get_stop: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_subprofiles: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_next: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_set_name: bool (struct tevent_req_profile *, const char *) +tevent_req_profile_set_start: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_profile_set_status: void (struct tevent_req_profile *, pid_t, enum tevent_req_state, uint64_t) +tevent_req_profile_set_stop: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_received: void (struct tevent_req *) +tevent_req_reset_endtime: 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_req_set_profile: bool (struct tevent_req *) +tevent_sa_info_queue_count: size_t (void) +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_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, 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_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/ABI/tevent-0.10.2.sigs b/lib/tevent/ABI/tevent-0.10.2.sigs new file mode 100644 index 0000000..f6227db --- /dev/null +++ b/lib/tevent/ABI/tevent-0.10.2.sigs @@ -0,0 +1,126 @@ +_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_context_pop_use: void (struct tevent_context *, const char *) +_tevent_context_push_use: bool (struct tevent_context *, const char *) +_tevent_context_wrapper_create: struct tevent_context *(struct tevent_context *, TALLOC_CTX *, const struct tevent_wrapper_ops *, void *, size_t, 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_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_abort: void (struct tevent_context *, 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_double_free: void (TALLOC_CTX *, 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_have_events: bool (struct tevent_context *) +tevent_common_invoke_fd_handler: int (struct tevent_fd *, uint16_t, bool *) +tevent_common_invoke_immediate_handler: int (struct tevent_immediate *, bool *) +tevent_common_invoke_signal_handler: int (struct tevent_signal *, int, int, void *, bool *) +tevent_common_invoke_timer_handler: int (struct tevent_timer *, struct timeval, bool *) +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_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +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_context_is_wrapper: bool (struct tevent_context *) +tevent_context_same_loop: bool (struct tevent_context *, struct tevent_context *) +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_num_signals: size_t (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_entry_untrigger: void (struct tevent_queue_entry *) +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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_get_profile: const struct tevent_req_profile *(struct tevent_req *) +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_move_profile: struct tevent_req_profile *(struct tevent_req *, TALLOC_CTX *) +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_profile_append_sub: void (struct tevent_req_profile *, struct tevent_req_profile **) +tevent_req_profile_create: struct tevent_req_profile *(TALLOC_CTX *) +tevent_req_profile_get_name: void (const struct tevent_req_profile *, const char **) +tevent_req_profile_get_start: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_status: void (const struct tevent_req_profile *, pid_t *, enum tevent_req_state *, uint64_t *) +tevent_req_profile_get_stop: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_subprofiles: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_next: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_set_name: bool (struct tevent_req_profile *, const char *) +tevent_req_profile_set_start: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_profile_set_status: void (struct tevent_req_profile *, pid_t, enum tevent_req_state, uint64_t) +tevent_req_profile_set_stop: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_received: void (struct tevent_req *) +tevent_req_reset_endtime: 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_req_set_profile: bool (struct tevent_req *) +tevent_sa_info_queue_count: size_t (void) +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_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, 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_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/ABI/tevent-0.11.0.sigs b/lib/tevent/ABI/tevent-0.11.0.sigs new file mode 100644 index 0000000..e64007e --- /dev/null +++ b/lib/tevent/ABI/tevent-0.11.0.sigs @@ -0,0 +1,146 @@ +_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_context_pop_use: void (struct tevent_context *, const char *) +_tevent_context_push_use: bool (struct tevent_context *, const char *) +_tevent_context_wrapper_create: struct tevent_context *(struct tevent_context *, TALLOC_CTX *, const struct tevent_wrapper_ops *, void *, size_t, 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_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_abort: void (struct tevent_context *, 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_double_free: void (TALLOC_CTX *, 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_have_events: bool (struct tevent_context *) +tevent_common_invoke_fd_handler: int (struct tevent_fd *, uint16_t, bool *) +tevent_common_invoke_immediate_handler: int (struct tevent_immediate *, bool *) +tevent_common_invoke_signal_handler: int (struct tevent_signal *, int, int, void *, bool *) +tevent_common_invoke_timer_handler: int (struct tevent_timer *, struct timeval, bool *) +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_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +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_context_is_wrapper: bool (struct tevent_context *) +tevent_context_same_loop: bool (struct tevent_context *, struct tevent_context *) +tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...) +tevent_fd_get_flags: uint16_t (struct tevent_fd *) +tevent_fd_get_tag: uint64_t (const 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_fd_set_tag: void (struct tevent_fd *, uint64_t) +tevent_get_trace_callback: void (struct tevent_context *, tevent_trace_callback_t *, void *) +tevent_get_trace_fd_callback: void (struct tevent_context *, tevent_trace_fd_callback_t *, void *) +tevent_get_trace_immediate_callback: void (struct tevent_context *, tevent_trace_immediate_callback_t *, void *) +tevent_get_trace_signal_callback: void (struct tevent_context *, tevent_trace_signal_callback_t *, void *) +tevent_get_trace_timer_callback: void (struct tevent_context *, tevent_trace_timer_callback_t *, void *) +tevent_immediate_get_tag: uint64_t (const struct tevent_immediate *) +tevent_immediate_set_tag: void (struct tevent_immediate *, uint64_t) +tevent_loop_allow_nesting: void (struct tevent_context *) +tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *) +tevent_num_signals: size_t (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_entry_untrigger: void (struct tevent_queue_entry *) +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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_get_profile: const struct tevent_req_profile *(struct tevent_req *) +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_move_profile: struct tevent_req_profile *(struct tevent_req *, TALLOC_CTX *) +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_profile_append_sub: void (struct tevent_req_profile *, struct tevent_req_profile **) +tevent_req_profile_create: struct tevent_req_profile *(TALLOC_CTX *) +tevent_req_profile_get_name: void (const struct tevent_req_profile *, const char **) +tevent_req_profile_get_start: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_status: void (const struct tevent_req_profile *, pid_t *, enum tevent_req_state *, uint64_t *) +tevent_req_profile_get_stop: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_subprofiles: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_next: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_set_name: bool (struct tevent_req_profile *, const char *) +tevent_req_profile_set_start: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_profile_set_status: void (struct tevent_req_profile *, pid_t, enum tevent_req_state, uint64_t) +tevent_req_profile_set_stop: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_received: void (struct tevent_req *) +tevent_req_reset_endtime: 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_req_set_profile: bool (struct tevent_req *) +tevent_sa_info_queue_count: size_t (void) +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_set_trace_fd_callback: void (struct tevent_context *, tevent_trace_fd_callback_t, void *) +tevent_set_trace_immediate_callback: void (struct tevent_context *, tevent_trace_immediate_callback_t, void *) +tevent_set_trace_signal_callback: void (struct tevent_context *, tevent_trace_signal_callback_t, void *) +tevent_set_trace_timer_callback: void (struct tevent_context *, tevent_trace_timer_callback_t, void *) +tevent_signal_get_tag: uint64_t (const struct tevent_signal *) +tevent_signal_set_tag: void (struct tevent_signal *, uint64_t) +tevent_signal_support: bool (struct tevent_context *) +tevent_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, struct tevent_context *) +tevent_timer_get_tag: uint64_t (const struct tevent_timer *) +tevent_timer_set_tag: void (struct tevent_timer *, uint64_t) +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_fd_callback: void (struct tevent_context *, struct tevent_fd *, enum tevent_event_trace_point) +tevent_trace_immediate_callback: void (struct tevent_context *, struct tevent_immediate *, enum tevent_event_trace_point) +tevent_trace_point_callback: void (struct tevent_context *, enum tevent_trace_point) +tevent_trace_signal_callback: void (struct tevent_context *, struct tevent_signal *, enum tevent_event_trace_point) +tevent_trace_timer_callback: void (struct tevent_context *, struct tevent_timer *, enum tevent_event_trace_point) +tevent_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/ABI/tevent-0.12.0.sigs b/lib/tevent/ABI/tevent-0.12.0.sigs new file mode 100644 index 0000000..22a8ce3 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.12.0.sigs @@ -0,0 +1,151 @@ +_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_context_pop_use: void (struct tevent_context *, const char *) +_tevent_context_push_use: bool (struct tevent_context *, const char *) +_tevent_context_wrapper_create: struct tevent_context *(struct tevent_context *, TALLOC_CTX *, const struct tevent_wrapper_ops *, void *, size_t, 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_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_abort: void (struct tevent_context *, 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_double_free: void (TALLOC_CTX *, 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_have_events: bool (struct tevent_context *) +tevent_common_invoke_fd_handler: int (struct tevent_fd *, uint16_t, bool *) +tevent_common_invoke_immediate_handler: int (struct tevent_immediate *, bool *) +tevent_common_invoke_signal_handler: int (struct tevent_signal *, int, int, void *, bool *) +tevent_common_invoke_timer_handler: int (struct tevent_timer *, struct timeval, bool *) +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_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +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_context_is_wrapper: bool (struct tevent_context *) +tevent_context_same_loop: bool (struct tevent_context *, struct tevent_context *) +tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...) +tevent_fd_get_flags: uint16_t (struct tevent_fd *) +tevent_fd_get_tag: uint64_t (const 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_fd_set_tag: void (struct tevent_fd *, uint64_t) +tevent_get_trace_callback: void (struct tevent_context *, tevent_trace_callback_t *, void *) +tevent_get_trace_fd_callback: void (struct tevent_context *, tevent_trace_fd_callback_t *, void *) +tevent_get_trace_immediate_callback: void (struct tevent_context *, tevent_trace_immediate_callback_t *, void *) +tevent_get_trace_queue_callback: void (struct tevent_context *, tevent_trace_queue_callback_t *, void *) +tevent_get_trace_signal_callback: void (struct tevent_context *, tevent_trace_signal_callback_t *, void *) +tevent_get_trace_timer_callback: void (struct tevent_context *, tevent_trace_timer_callback_t *, void *) +tevent_immediate_get_tag: uint64_t (const struct tevent_immediate *) +tevent_immediate_set_tag: void (struct tevent_immediate *, uint64_t) +tevent_queue_entry_get_tag: uint64_t (const struct tevent_queue_entry *) +tevent_queue_entry_set_tag: void (struct tevent_queue_entry *, uint64_t) +tevent_loop_allow_nesting: void (struct tevent_context *) +tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *) +tevent_num_signals: size_t (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_entry_untrigger: void (struct tevent_queue_entry *) +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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_get_profile: const struct tevent_req_profile *(struct tevent_req *) +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_move_profile: struct tevent_req_profile *(struct tevent_req *, TALLOC_CTX *) +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_profile_append_sub: void (struct tevent_req_profile *, struct tevent_req_profile **) +tevent_req_profile_create: struct tevent_req_profile *(TALLOC_CTX *) +tevent_req_profile_get_name: void (const struct tevent_req_profile *, const char **) +tevent_req_profile_get_start: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_status: void (const struct tevent_req_profile *, pid_t *, enum tevent_req_state *, uint64_t *) +tevent_req_profile_get_stop: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_subprofiles: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_next: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_set_name: bool (struct tevent_req_profile *, const char *) +tevent_req_profile_set_start: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_profile_set_status: void (struct tevent_req_profile *, pid_t, enum tevent_req_state, uint64_t) +tevent_req_profile_set_stop: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_received: void (struct tevent_req *) +tevent_req_reset_endtime: 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_req_set_profile: bool (struct tevent_req *) +tevent_sa_info_queue_count: size_t (void) +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_set_trace_fd_callback: void (struct tevent_context *, tevent_trace_fd_callback_t, void *) +tevent_set_trace_immediate_callback: void (struct tevent_context *, tevent_trace_immediate_callback_t, void *) +tevent_set_trace_queue_callback: void (struct tevent_context *, tevent_trace_queue_callback_t, void *) +tevent_set_trace_signal_callback: void (struct tevent_context *, tevent_trace_signal_callback_t, void *) +tevent_set_trace_timer_callback: void (struct tevent_context *, tevent_trace_timer_callback_t, void *) +tevent_signal_get_tag: uint64_t (const struct tevent_signal *) +tevent_signal_set_tag: void (struct tevent_signal *, uint64_t) +tevent_signal_support: bool (struct tevent_context *) +tevent_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, struct tevent_context *) +tevent_timer_get_tag: uint64_t (const struct tevent_timer *) +tevent_timer_set_tag: void (struct tevent_timer *, uint64_t) +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_fd_callback: void (struct tevent_context *, struct tevent_fd *, enum tevent_event_trace_point) +tevent_trace_immediate_callback: void (struct tevent_context *, struct tevent_immediate *, enum tevent_event_trace_point) +tevent_trace_queue_callback: void (struct tevent_context *, struct tevent_queue_entry *, enum tevent_event_trace_point) +tevent_trace_point_callback: void (struct tevent_context *, enum tevent_trace_point) +tevent_trace_signal_callback: void (struct tevent_context *, struct tevent_signal *, enum tevent_event_trace_point) +tevent_trace_timer_callback: void (struct tevent_context *, struct tevent_timer *, enum tevent_event_trace_point) +tevent_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/ABI/tevent-0.12.1.sigs b/lib/tevent/ABI/tevent-0.12.1.sigs new file mode 100644 index 0000000..0e4d1e1 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.12.1.sigs @@ -0,0 +1,151 @@ +_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_context_pop_use: void (struct tevent_context *, const char *) +_tevent_context_push_use: bool (struct tevent_context *, const char *) +_tevent_context_wrapper_create: struct tevent_context *(struct tevent_context *, TALLOC_CTX *, const struct tevent_wrapper_ops *, void *, size_t, 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_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_abort: void (struct tevent_context *, 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_double_free: void (TALLOC_CTX *, 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_have_events: bool (struct tevent_context *) +tevent_common_invoke_fd_handler: int (struct tevent_fd *, uint16_t, bool *) +tevent_common_invoke_immediate_handler: int (struct tevent_immediate *, bool *) +tevent_common_invoke_signal_handler: int (struct tevent_signal *, int, int, void *, bool *) +tevent_common_invoke_timer_handler: int (struct tevent_timer *, struct timeval, bool *) +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_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +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_context_is_wrapper: bool (struct tevent_context *) +tevent_context_same_loop: bool (struct tevent_context *, struct tevent_context *) +tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...) +tevent_fd_get_flags: uint16_t (struct tevent_fd *) +tevent_fd_get_tag: uint64_t (const 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_fd_set_tag: void (struct tevent_fd *, uint64_t) +tevent_get_trace_callback: void (struct tevent_context *, tevent_trace_callback_t *, void *) +tevent_get_trace_fd_callback: void (struct tevent_context *, tevent_trace_fd_callback_t *, void *) +tevent_get_trace_immediate_callback: void (struct tevent_context *, tevent_trace_immediate_callback_t *, void *) +tevent_get_trace_queue_callback: void (struct tevent_context *, tevent_trace_queue_callback_t *, void *) +tevent_get_trace_signal_callback: void (struct tevent_context *, tevent_trace_signal_callback_t *, void *) +tevent_get_trace_timer_callback: void (struct tevent_context *, tevent_trace_timer_callback_t *, void *) +tevent_immediate_get_tag: uint64_t (const struct tevent_immediate *) +tevent_immediate_set_tag: void (struct tevent_immediate *, uint64_t) +tevent_loop_allow_nesting: void (struct tevent_context *) +tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *) +tevent_num_signals: size_t (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_entry_get_tag: uint64_t (const struct tevent_queue_entry *) +tevent_queue_entry_set_tag: void (struct tevent_queue_entry *, uint64_t) +tevent_queue_entry_untrigger: void (struct tevent_queue_entry *) +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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_get_profile: const struct tevent_req_profile *(struct tevent_req *) +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_move_profile: struct tevent_req_profile *(struct tevent_req *, TALLOC_CTX *) +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_profile_append_sub: void (struct tevent_req_profile *, struct tevent_req_profile **) +tevent_req_profile_create: struct tevent_req_profile *(TALLOC_CTX *) +tevent_req_profile_get_name: void (const struct tevent_req_profile *, const char **) +tevent_req_profile_get_start: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_status: void (const struct tevent_req_profile *, pid_t *, enum tevent_req_state *, uint64_t *) +tevent_req_profile_get_stop: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_subprofiles: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_next: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_set_name: bool (struct tevent_req_profile *, const char *) +tevent_req_profile_set_start: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_profile_set_status: void (struct tevent_req_profile *, pid_t, enum tevent_req_state, uint64_t) +tevent_req_profile_set_stop: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_received: void (struct tevent_req *) +tevent_req_reset_endtime: 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_req_set_profile: bool (struct tevent_req *) +tevent_sa_info_queue_count: size_t (void) +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_set_trace_fd_callback: void (struct tevent_context *, tevent_trace_fd_callback_t, void *) +tevent_set_trace_immediate_callback: void (struct tevent_context *, tevent_trace_immediate_callback_t, void *) +tevent_set_trace_queue_callback: void (struct tevent_context *, tevent_trace_queue_callback_t, void *) +tevent_set_trace_signal_callback: void (struct tevent_context *, tevent_trace_signal_callback_t, void *) +tevent_set_trace_timer_callback: void (struct tevent_context *, tevent_trace_timer_callback_t, void *) +tevent_signal_get_tag: uint64_t (const struct tevent_signal *) +tevent_signal_set_tag: void (struct tevent_signal *, uint64_t) +tevent_signal_support: bool (struct tevent_context *) +tevent_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, struct tevent_context *) +tevent_timer_get_tag: uint64_t (const struct tevent_timer *) +tevent_timer_set_tag: void (struct tevent_timer *, uint64_t) +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_fd_callback: void (struct tevent_context *, struct tevent_fd *, enum tevent_event_trace_point) +tevent_trace_immediate_callback: void (struct tevent_context *, struct tevent_immediate *, enum tevent_event_trace_point) +tevent_trace_point_callback: void (struct tevent_context *, enum tevent_trace_point) +tevent_trace_queue_callback: void (struct tevent_context *, struct tevent_queue_entry *, enum tevent_event_trace_point) +tevent_trace_signal_callback: void (struct tevent_context *, struct tevent_signal *, enum tevent_event_trace_point) +tevent_trace_timer_callback: void (struct tevent_context *, struct tevent_timer *, enum tevent_event_trace_point) +tevent_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/ABI/tevent-0.13.0.sigs b/lib/tevent/ABI/tevent-0.13.0.sigs new file mode 100644 index 0000000..68722a0 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.13.0.sigs @@ -0,0 +1,152 @@ +_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_context_pop_use: void (struct tevent_context *, const char *) +_tevent_context_push_use: bool (struct tevent_context *, const char *) +_tevent_context_wrapper_create: struct tevent_context *(struct tevent_context *, TALLOC_CTX *, const struct tevent_wrapper_ops *, void *, size_t, 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_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_abort: void (struct tevent_context *, const char *) +tevent_backend_list: const char **(TALLOC_CTX *) +tevent_cached_getpid: pid_t (void) +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_double_free: void (TALLOC_CTX *, 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_have_events: bool (struct tevent_context *) +tevent_common_invoke_fd_handler: int (struct tevent_fd *, uint16_t, bool *) +tevent_common_invoke_immediate_handler: int (struct tevent_immediate *, bool *) +tevent_common_invoke_signal_handler: int (struct tevent_signal *, int, int, void *, bool *) +tevent_common_invoke_timer_handler: int (struct tevent_timer *, struct timeval, bool *) +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_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +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_context_is_wrapper: bool (struct tevent_context *) +tevent_context_same_loop: bool (struct tevent_context *, struct tevent_context *) +tevent_debug: void (struct tevent_context *, enum tevent_debug_level, const char *, ...) +tevent_fd_get_flags: uint16_t (struct tevent_fd *) +tevent_fd_get_tag: uint64_t (const 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_fd_set_tag: void (struct tevent_fd *, uint64_t) +tevent_get_trace_callback: void (struct tevent_context *, tevent_trace_callback_t *, void *) +tevent_get_trace_fd_callback: void (struct tevent_context *, tevent_trace_fd_callback_t *, void *) +tevent_get_trace_immediate_callback: void (struct tevent_context *, tevent_trace_immediate_callback_t *, void *) +tevent_get_trace_queue_callback: void (struct tevent_context *, tevent_trace_queue_callback_t *, void *) +tevent_get_trace_signal_callback: void (struct tevent_context *, tevent_trace_signal_callback_t *, void *) +tevent_get_trace_timer_callback: void (struct tevent_context *, tevent_trace_timer_callback_t *, void *) +tevent_immediate_get_tag: uint64_t (const struct tevent_immediate *) +tevent_immediate_set_tag: void (struct tevent_immediate *, uint64_t) +tevent_loop_allow_nesting: void (struct tevent_context *) +tevent_loop_set_nesting_hook: void (struct tevent_context *, tevent_nesting_hook, void *) +tevent_num_signals: size_t (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_entry_get_tag: uint64_t (const struct tevent_queue_entry *) +tevent_queue_entry_set_tag: void (struct tevent_queue_entry *, uint64_t) +tevent_queue_entry_untrigger: void (struct tevent_queue_entry *) +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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_get_profile: const struct tevent_req_profile *(struct tevent_req *) +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_move_profile: struct tevent_req_profile *(struct tevent_req *, TALLOC_CTX *) +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_profile_append_sub: void (struct tevent_req_profile *, struct tevent_req_profile **) +tevent_req_profile_create: struct tevent_req_profile *(TALLOC_CTX *) +tevent_req_profile_get_name: void (const struct tevent_req_profile *, const char **) +tevent_req_profile_get_start: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_status: void (const struct tevent_req_profile *, pid_t *, enum tevent_req_state *, uint64_t *) +tevent_req_profile_get_stop: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_subprofiles: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_next: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_set_name: bool (struct tevent_req_profile *, const char *) +tevent_req_profile_set_start: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_profile_set_status: void (struct tevent_req_profile *, pid_t, enum tevent_req_state, uint64_t) +tevent_req_profile_set_stop: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_received: void (struct tevent_req *) +tevent_req_reset_endtime: 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_req_set_profile: bool (struct tevent_req *) +tevent_sa_info_queue_count: size_t (void) +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_set_trace_fd_callback: void (struct tevent_context *, tevent_trace_fd_callback_t, void *) +tevent_set_trace_immediate_callback: void (struct tevent_context *, tevent_trace_immediate_callback_t, void *) +tevent_set_trace_queue_callback: void (struct tevent_context *, tevent_trace_queue_callback_t, void *) +tevent_set_trace_signal_callback: void (struct tevent_context *, tevent_trace_signal_callback_t, void *) +tevent_set_trace_timer_callback: void (struct tevent_context *, tevent_trace_timer_callback_t, void *) +tevent_signal_get_tag: uint64_t (const struct tevent_signal *) +tevent_signal_set_tag: void (struct tevent_signal *, uint64_t) +tevent_signal_support: bool (struct tevent_context *) +tevent_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, struct tevent_context *) +tevent_timer_get_tag: uint64_t (const struct tevent_timer *) +tevent_timer_set_tag: void (struct tevent_timer *, uint64_t) +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_fd_callback: void (struct tevent_context *, struct tevent_fd *, enum tevent_event_trace_point) +tevent_trace_immediate_callback: void (struct tevent_context *, struct tevent_immediate *, enum tevent_event_trace_point) +tevent_trace_point_callback: void (struct tevent_context *, enum tevent_trace_point) +tevent_trace_queue_callback: void (struct tevent_context *, struct tevent_queue_entry *, enum tevent_event_trace_point) +tevent_trace_signal_callback: void (struct tevent_context *, struct tevent_signal *, enum tevent_event_trace_point) +tevent_trace_timer_callback: void (struct tevent_context *, struct tevent_timer *, enum tevent_event_trace_point) +tevent_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/ABI/tevent-0.9.10.sigs b/lib/tevent/ABI/tevent-0.9.10.sigs new file mode 100644 index 0000000..9adaba5 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.10.sigs @@ -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) diff --git a/lib/tevent/ABI/tevent-0.9.11.sigs b/lib/tevent/ABI/tevent-0.9.11.sigs new file mode 100644 index 0000000..9adaba5 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.11.sigs @@ -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) diff --git a/lib/tevent/ABI/tevent-0.9.12.sigs b/lib/tevent/ABI/tevent-0.9.12.sigs new file mode 100644 index 0000000..df9b08d --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.12.sigs @@ -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) diff --git a/lib/tevent/ABI/tevent-0.9.13.sigs b/lib/tevent/ABI/tevent-0.9.13.sigs new file mode 100644 index 0000000..888ca0e --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.13.sigs @@ -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) diff --git a/lib/tevent/ABI/tevent-0.9.14.sigs b/lib/tevent/ABI/tevent-0.9.14.sigs new file mode 100644 index 0000000..13c461c --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.14.sigs @@ -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) diff --git a/lib/tevent/ABI/tevent-0.9.15.sigs b/lib/tevent/ABI/tevent-0.9.15.sigs new file mode 100644 index 0000000..13c461c --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.15.sigs @@ -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) diff --git a/lib/tevent/ABI/tevent-0.9.16.sigs b/lib/tevent/ABI/tevent-0.9.16.sigs new file mode 100644 index 0000000..ea7f944 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.16.sigs @@ -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) diff --git a/lib/tevent/ABI/tevent-0.9.17.sigs b/lib/tevent/ABI/tevent-0.9.17.sigs new file mode 100644 index 0000000..ea7f944 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.17.sigs @@ -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) diff --git a/lib/tevent/ABI/tevent-0.9.18.sigs b/lib/tevent/ABI/tevent-0.9.18.sigs new file mode 100644 index 0000000..70d20b6 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.18.sigs @@ -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) diff --git a/lib/tevent/ABI/tevent-0.9.19.sigs b/lib/tevent/ABI/tevent-0.9.19.sigs new file mode 100644 index 0000000..70d20b6 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.19.sigs @@ -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) diff --git a/lib/tevent/ABI/tevent-0.9.20.sigs b/lib/tevent/ABI/tevent-0.9.20.sigs new file mode 100644 index 0000000..7b9c77d --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.20.sigs @@ -0,0 +1,87 @@ +_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_num_signals: size_t (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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_sa_info_queue_count: size_t (void) +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) diff --git a/lib/tevent/ABI/tevent-0.9.21.sigs b/lib/tevent/ABI/tevent-0.9.21.sigs new file mode 100644 index 0000000..d8b9f4b --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.21.sigs @@ -0,0 +1,88 @@ +_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_num_signals: size_t (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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_sa_info_queue_count: size_t (void) +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) diff --git a/lib/tevent/ABI/tevent-0.9.22.sigs b/lib/tevent/ABI/tevent-0.9.22.sigs new file mode 100644 index 0000000..d8b9f4b --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.22.sigs @@ -0,0 +1,88 @@ +_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_num_signals: size_t (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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_sa_info_queue_count: size_t (void) +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) diff --git a/lib/tevent/ABI/tevent-0.9.23.sigs b/lib/tevent/ABI/tevent-0.9.23.sigs new file mode 100644 index 0000000..d8b9f4b --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.23.sigs @@ -0,0 +1,88 @@ +_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_num_signals: size_t (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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_sa_info_queue_count: size_t (void) +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) diff --git a/lib/tevent/ABI/tevent-0.9.24.sigs b/lib/tevent/ABI/tevent-0.9.24.sigs new file mode 100644 index 0000000..d8b9f4b --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.24.sigs @@ -0,0 +1,88 @@ +_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_num_signals: size_t (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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_sa_info_queue_count: size_t (void) +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) diff --git a/lib/tevent/ABI/tevent-0.9.25.sigs b/lib/tevent/ABI/tevent-0.9.25.sigs new file mode 100644 index 0000000..d8b9f4b --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.25.sigs @@ -0,0 +1,88 @@ +_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_num_signals: size_t (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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_sa_info_queue_count: size_t (void) +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) diff --git a/lib/tevent/ABI/tevent-0.9.26.sigs b/lib/tevent/ABI/tevent-0.9.26.sigs new file mode 100644 index 0000000..1357751 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.26.sigs @@ -0,0 +1,90 @@ +_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_num_signals: size_t (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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_sa_info_queue_count: size_t (void) +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_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +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) diff --git a/lib/tevent/ABI/tevent-0.9.27.sigs b/lib/tevent/ABI/tevent-0.9.27.sigs new file mode 100644 index 0000000..1357751 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.27.sigs @@ -0,0 +1,90 @@ +_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_num_signals: size_t (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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_sa_info_queue_count: size_t (void) +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_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +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) diff --git a/lib/tevent/ABI/tevent-0.9.28.sigs b/lib/tevent/ABI/tevent-0.9.28.sigs new file mode 100644 index 0000000..1357751 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.28.sigs @@ -0,0 +1,90 @@ +_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_num_signals: size_t (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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_sa_info_queue_count: size_t (void) +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_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +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) diff --git a/lib/tevent/ABI/tevent-0.9.29.sigs b/lib/tevent/ABI/tevent-0.9.29.sigs new file mode 100644 index 0000000..1357751 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.29.sigs @@ -0,0 +1,90 @@ +_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_num_signals: size_t (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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_sa_info_queue_count: size_t (void) +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_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +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) diff --git a/lib/tevent/ABI/tevent-0.9.30.sigs b/lib/tevent/ABI/tevent-0.9.30.sigs new file mode 100644 index 0000000..9b8bfa1 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.30.sigs @@ -0,0 +1,96 @@ +_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_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, 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_have_events: bool (struct tevent_context *) +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_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_init: int (struct tevent_context *) +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_num_signals: size_t (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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_sa_info_queue_count: size_t (void) +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_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, 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) diff --git a/lib/tevent/ABI/tevent-0.9.31.sigs b/lib/tevent/ABI/tevent-0.9.31.sigs new file mode 100644 index 0000000..7a6a236 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.31.sigs @@ -0,0 +1,99 @@ +_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_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, 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_have_events: bool (struct tevent_context *) +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_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +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_num_signals: size_t (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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_reset_endtime: 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_sa_info_queue_count: size_t (void) +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_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, 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_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/ABI/tevent-0.9.32.sigs b/lib/tevent/ABI/tevent-0.9.32.sigs new file mode 100644 index 0000000..7a6a236 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.32.sigs @@ -0,0 +1,99 @@ +_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_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, 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_have_events: bool (struct tevent_context *) +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_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +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_num_signals: size_t (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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_reset_endtime: 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_sa_info_queue_count: size_t (void) +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_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, 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_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/ABI/tevent-0.9.33.sigs b/lib/tevent/ABI/tevent-0.9.33.sigs new file mode 100644 index 0000000..7a6a236 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.33.sigs @@ -0,0 +1,99 @@ +_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_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, 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_have_events: bool (struct tevent_context *) +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_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +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_num_signals: size_t (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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_reset_endtime: 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_sa_info_queue_count: size_t (void) +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_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, 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_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/ABI/tevent-0.9.34.sigs b/lib/tevent/ABI/tevent-0.9.34.sigs new file mode 100644 index 0000000..7a6a236 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.34.sigs @@ -0,0 +1,99 @@ +_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_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, 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_have_events: bool (struct tevent_context *) +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_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +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_num_signals: size_t (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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_reset_endtime: 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_sa_info_queue_count: size_t (void) +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_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, 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_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/ABI/tevent-0.9.35.sigs b/lib/tevent/ABI/tevent-0.9.35.sigs new file mode 100644 index 0000000..7a6a236 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.35.sigs @@ -0,0 +1,99 @@ +_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_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, 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_have_events: bool (struct tevent_context *) +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_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +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_num_signals: size_t (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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_reset_endtime: 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_sa_info_queue_count: size_t (void) +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_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, 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_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/ABI/tevent-0.9.36.sigs b/lib/tevent/ABI/tevent-0.9.36.sigs new file mode 100644 index 0000000..8a579c8 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.36.sigs @@ -0,0 +1,100 @@ +_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_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, 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_have_events: bool (struct tevent_context *) +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_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +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_num_signals: size_t (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_entry_untrigger: void (struct tevent_queue_entry *) +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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_reset_endtime: 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_sa_info_queue_count: size_t (void) +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_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, 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_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/ABI/tevent-0.9.37.sigs b/lib/tevent/ABI/tevent-0.9.37.sigs new file mode 100644 index 0000000..f6227db --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.37.sigs @@ -0,0 +1,126 @@ +_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_context_pop_use: void (struct tevent_context *, const char *) +_tevent_context_push_use: bool (struct tevent_context *, const char *) +_tevent_context_wrapper_create: struct tevent_context *(struct tevent_context *, TALLOC_CTX *, const struct tevent_wrapper_ops *, void *, size_t, 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_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_abort: void (struct tevent_context *, 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_double_free: void (TALLOC_CTX *, 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_have_events: bool (struct tevent_context *) +tevent_common_invoke_fd_handler: int (struct tevent_fd *, uint16_t, bool *) +tevent_common_invoke_immediate_handler: int (struct tevent_immediate *, bool *) +tevent_common_invoke_signal_handler: int (struct tevent_signal *, int, int, void *, bool *) +tevent_common_invoke_timer_handler: int (struct tevent_timer *, struct timeval, bool *) +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_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +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_context_is_wrapper: bool (struct tevent_context *) +tevent_context_same_loop: bool (struct tevent_context *, struct tevent_context *) +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_num_signals: size_t (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_entry_untrigger: void (struct tevent_queue_entry *) +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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_get_profile: const struct tevent_req_profile *(struct tevent_req *) +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_move_profile: struct tevent_req_profile *(struct tevent_req *, TALLOC_CTX *) +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_profile_append_sub: void (struct tevent_req_profile *, struct tevent_req_profile **) +tevent_req_profile_create: struct tevent_req_profile *(TALLOC_CTX *) +tevent_req_profile_get_name: void (const struct tevent_req_profile *, const char **) +tevent_req_profile_get_start: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_status: void (const struct tevent_req_profile *, pid_t *, enum tevent_req_state *, uint64_t *) +tevent_req_profile_get_stop: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_subprofiles: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_next: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_set_name: bool (struct tevent_req_profile *, const char *) +tevent_req_profile_set_start: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_profile_set_status: void (struct tevent_req_profile *, pid_t, enum tevent_req_state, uint64_t) +tevent_req_profile_set_stop: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_received: void (struct tevent_req *) +tevent_req_reset_endtime: 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_req_set_profile: bool (struct tevent_req *) +tevent_sa_info_queue_count: size_t (void) +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_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, 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_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/ABI/tevent-0.9.38.sigs b/lib/tevent/ABI/tevent-0.9.38.sigs new file mode 100644 index 0000000..f6227db --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.38.sigs @@ -0,0 +1,126 @@ +_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_context_pop_use: void (struct tevent_context *, const char *) +_tevent_context_push_use: bool (struct tevent_context *, const char *) +_tevent_context_wrapper_create: struct tevent_context *(struct tevent_context *, TALLOC_CTX *, const struct tevent_wrapper_ops *, void *, size_t, 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_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_abort: void (struct tevent_context *, 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_double_free: void (TALLOC_CTX *, 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_have_events: bool (struct tevent_context *) +tevent_common_invoke_fd_handler: int (struct tevent_fd *, uint16_t, bool *) +tevent_common_invoke_immediate_handler: int (struct tevent_immediate *, bool *) +tevent_common_invoke_signal_handler: int (struct tevent_signal *, int, int, void *, bool *) +tevent_common_invoke_timer_handler: int (struct tevent_timer *, struct timeval, bool *) +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_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +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_context_is_wrapper: bool (struct tevent_context *) +tevent_context_same_loop: bool (struct tevent_context *, struct tevent_context *) +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_num_signals: size_t (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_entry_untrigger: void (struct tevent_queue_entry *) +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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_get_profile: const struct tevent_req_profile *(struct tevent_req *) +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_move_profile: struct tevent_req_profile *(struct tevent_req *, TALLOC_CTX *) +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_profile_append_sub: void (struct tevent_req_profile *, struct tevent_req_profile **) +tevent_req_profile_create: struct tevent_req_profile *(TALLOC_CTX *) +tevent_req_profile_get_name: void (const struct tevent_req_profile *, const char **) +tevent_req_profile_get_start: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_status: void (const struct tevent_req_profile *, pid_t *, enum tevent_req_state *, uint64_t *) +tevent_req_profile_get_stop: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_subprofiles: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_next: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_set_name: bool (struct tevent_req_profile *, const char *) +tevent_req_profile_set_start: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_profile_set_status: void (struct tevent_req_profile *, pid_t, enum tevent_req_state, uint64_t) +tevent_req_profile_set_stop: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_received: void (struct tevent_req *) +tevent_req_reset_endtime: 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_req_set_profile: bool (struct tevent_req *) +tevent_sa_info_queue_count: size_t (void) +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_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, 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_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/ABI/tevent-0.9.39.sigs b/lib/tevent/ABI/tevent-0.9.39.sigs new file mode 100644 index 0000000..f6227db --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.39.sigs @@ -0,0 +1,126 @@ +_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_context_pop_use: void (struct tevent_context *, const char *) +_tevent_context_push_use: bool (struct tevent_context *, const char *) +_tevent_context_wrapper_create: struct tevent_context *(struct tevent_context *, TALLOC_CTX *, const struct tevent_wrapper_ops *, void *, size_t, 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_threaded_schedule_immediate: void (struct tevent_threaded_context *, struct tevent_immediate *, tevent_immediate_handler_t, void *, const char *, const char *) +tevent_abort: void (struct tevent_context *, 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_double_free: void (TALLOC_CTX *, 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_have_events: bool (struct tevent_context *) +tevent_common_invoke_fd_handler: int (struct tevent_fd *, uint16_t, bool *) +tevent_common_invoke_immediate_handler: int (struct tevent_immediate *, bool *) +tevent_common_invoke_signal_handler: int (struct tevent_signal *, int, int, void *, bool *) +tevent_common_invoke_timer_handler: int (struct tevent_timer *, struct timeval, bool *) +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_common_threaded_activate_immediate: void (struct tevent_context *) +tevent_common_wakeup: int (struct tevent_context *) +tevent_common_wakeup_fd: int (int) +tevent_common_wakeup_init: int (struct tevent_context *) +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_context_is_wrapper: bool (struct tevent_context *) +tevent_context_same_loop: bool (struct tevent_context *, struct tevent_context *) +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_num_signals: size_t (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_entry_untrigger: void (struct tevent_queue_entry *) +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_queue_wait_recv: bool (struct tevent_req *) +tevent_queue_wait_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, 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_get_profile: const struct tevent_req_profile *(struct tevent_req *) +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_move_profile: struct tevent_req_profile *(struct tevent_req *, TALLOC_CTX *) +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_profile_append_sub: void (struct tevent_req_profile *, struct tevent_req_profile **) +tevent_req_profile_create: struct tevent_req_profile *(TALLOC_CTX *) +tevent_req_profile_get_name: void (const struct tevent_req_profile *, const char **) +tevent_req_profile_get_start: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_status: void (const struct tevent_req_profile *, pid_t *, enum tevent_req_state *, uint64_t *) +tevent_req_profile_get_stop: void (const struct tevent_req_profile *, const char **, struct timeval *) +tevent_req_profile_get_subprofiles: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_next: const struct tevent_req_profile *(const struct tevent_req_profile *) +tevent_req_profile_set_name: bool (struct tevent_req_profile *, const char *) +tevent_req_profile_set_start: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_profile_set_status: void (struct tevent_req_profile *, pid_t, enum tevent_req_state, uint64_t) +tevent_req_profile_set_stop: bool (struct tevent_req_profile *, const char *, struct timeval) +tevent_req_received: void (struct tevent_req *) +tevent_req_reset_endtime: 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_cleanup_fn: void (struct tevent_req *, tevent_req_cleanup_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_req_set_profile: bool (struct tevent_req *) +tevent_sa_info_queue_count: size_t (void) +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_thread_proxy_create: struct tevent_thread_proxy *(struct tevent_context *) +tevent_thread_proxy_schedule: void (struct tevent_thread_proxy *, struct tevent_immediate **, tevent_immediate_handler_t, void *) +tevent_threaded_context_create: struct tevent_threaded_context *(TALLOC_CTX *, 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_update_timer: void (struct tevent_timer *, struct timeval) +tevent_wakeup_recv: bool (struct tevent_req *) +tevent_wakeup_send: struct tevent_req *(TALLOC_CTX *, struct tevent_context *, struct timeval) diff --git a/lib/tevent/ABI/tevent-0.9.9.sigs b/lib/tevent/ABI/tevent-0.9.9.sigs new file mode 100644 index 0000000..9adaba5 --- /dev/null +++ b/lib/tevent/ABI/tevent-0.9.9.sigs @@ -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) diff --git a/lib/tevent/Makefile b/lib/tevent/Makefile new file mode 100644 index 0000000..6a3aab0 --- /dev/null +++ b/lib/tevent/Makefile @@ -0,0 +1,52 @@ +# simple makefile wrapper to run waf +WAF_BIN=`PATH=buildtools/bin:../../buildtools/bin:$$PATH which waf` +WAF_BINARY=$(PYTHON) $(WAF_BIN) +WAF=PYTHONHASHSEED=1 WAF_MAKE=1 $(WAF_BINARY) + +all: + $(WAF) build + +install: + $(WAF) install + +uninstall: + $(WAF) uninstall + +test: + $(WAF) test $(TEST_OPTIONS) + +dist: + touch .tmplock + WAFLOCK=.tmplock $(WAF) dist + +distcheck: + touch .tmplock + WAFLOCK=.tmplock $(WAF) distcheck + +clean: + $(WAF) clean + +distclean: + $(WAF) distclean + +reconfigure: configure + $(WAF) reconfigure + +show_waf_options: + $(WAF) --help + +# some compatibility make targets +everything: all + +testsuite: all + +check: test + +# this should do an install as well, once install is finished +installcheck: test + +etags: + $(WAF) etags + +ctags: + $(WAF) ctags diff --git a/lib/tevent/bindings.py b/lib/tevent/bindings.py new file mode 100644 index 0000000..f5e1499 --- /dev/null +++ b/lib/tevent/bindings.py @@ -0,0 +1,116 @@ +#!/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 +from unittest import TestCase, TestProgram +import gc + +import _tevent + + +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)) + + def test_timer(self): + """Test a timer is can be scheduled""" + collecting_list = [] + # time "0" has already passed, callback will be scheduled immediately + timer = self.ctx.add_timer(0, lambda t: collecting_list.append(True)) + self.assertTrue(timer.active) + self.assertEqual(collecting_list, []) + self.ctx.loop_once() + self.assertFalse(timer.active) + self.assertEqual(collecting_list, [True]) + + def test_timer_deallocate_timer(self): + """Test timer is scheduled even if reference to it isn't held""" + collecting_list = [] + + def callback(t): + collecting_list.append(True) + timer = self.ctx.add_timer(0, lambda t: collecting_list.append(True)) + gc.collect() + self.assertEqual(collecting_list, []) + self.ctx.loop_once() + self.assertEqual(collecting_list, [True]) + + def test_timer_deallocate_context(self): + """Test timer is unscheduled when context is freed""" + collecting_list = [] + + def callback(t): + collecting_list.append(True) + timer = self.ctx.add_timer(0, lambda t: collecting_list.append(True)) + self.assertTrue(timer.active) + del self.ctx + gc.collect() + self.assertEqual(collecting_list, []) + self.assertFalse(timer.active) + + def test_timer_offset(self): + """Test scheduling timer with an offset""" + collecting_list = [] + self.ctx.add_timer_offset(0.2, lambda t: collecting_list.append(2)) + self.ctx.add_timer_offset(0.1, lambda t: collecting_list.append(1)) + self.assertEqual(collecting_list, []) + self.ctx.loop_once() + self.assertEqual(collecting_list, [1]) + self.ctx.loop_once() + self.assertEqual(collecting_list, [1, 2]) + + +if __name__ == '__main__': + TestProgram() diff --git a/lib/tevent/configure b/lib/tevent/configure new file mode 100755 index 0000000..7b972bd --- /dev/null +++ b/lib/tevent/configure @@ -0,0 +1,28 @@ +#!/bin/sh + +PREVPATH=$(dirname $0) + +if [ -f $PREVPATH/../../buildtools/bin/waf ]; then + WAF=../../buildtools/bin/waf +elif [ -f $PREVPATH/buildtools/bin/waf ]; then + WAF=./buildtools/bin/waf +else + echo "tevent: Unable to find waf" + exit 1 +fi + +# using JOBS=1 gives maximum compatibility with +# systems like AIX which have broken threading in python +JOBS=1 +export JOBS + +# Make sure we don't have any library preloaded. +unset LD_PRELOAD + +# Make sure we get stable hashes +PYTHONHASHSEED=1 +export PYTHONHASHSEED + +cd . || exit 1 +$PYTHON $WAF configure "$@" || exit 1 +cd $PREVPATH diff --git a/lib/tevent/doc/img/tevent_context_stucture.png b/lib/tevent/doc/img/tevent_context_stucture.png Binary files differnew file mode 100644 index 0000000..fba8161 --- /dev/null +++ b/lib/tevent/doc/img/tevent_context_stucture.png diff --git a/lib/tevent/doc/img/tevent_subrequest.png b/lib/tevent/doc/img/tevent_subrequest.png Binary files differnew file mode 100644 index 0000000..ea79223 --- /dev/null +++ b/lib/tevent/doc/img/tevent_subrequest.png diff --git a/lib/tevent/doc/mainpage.dox b/lib/tevent/doc/mainpage.dox new file mode 100644 index 0000000..5b76013 --- /dev/null +++ b/lib/tevent/doc/mainpage.dox @@ -0,0 +1,47 @@ +/** + * @mainpage + * + * Tevent is an event system based on the talloc memory management library. It + * is the core event system used in Samba. + * + * The low level tevent has support for many event types, including timers, + * signals, and the classic file descriptor events. + * + * Tevent also provide helpers to deal with asynchronous code providing the + * tevent_req (tevent request) functions. + * + * @section main_tevent_tutorial Tutorial + * + * You should start by reading @subpage tevent_tutorial, then reading the + * documentation of the interesting functions as you go. + * + * @section main_tevent_download Download + * + * You can download the latest releases of tevent from the + * <a href="http://samba.org/ftp/tevent" target="_blank">tevent directory</a> + * on the samba public source archive. + * + * @section main_tevent_bugs Discussion and bug reports + * + * tevent does not currently have its own mailing list or bug tracking system. + * For now, please use the + * <a href="https://lists.samba.org/mailman/listinfo/samba-technical" target="_blank">samba-technical</a> + * mailing list, and the + * <a href="http://bugzilla.samba.org/" target="_blank">Samba bugzilla</a> + * bug tracking system. + * + * @section main_tevent_devel Development + * You can download the latest code either via git or rsync. + * + * To fetch via git see the following guide: + * + * <a href="http://wiki.samba.org/index.php/Using_Git_for_Samba_Development" target="_blank">Using Git for Samba Development</a> + * + * Once you have cloned the tree switch to the master branch and cd into the + * lib/tevent directory. + * + * To fetch via rsync use this command: + * + * rsync -Pavz samba.org::ftp/unpacked/standalone_projects/lib/tevent . + * + */ diff --git a/lib/tevent/doc/tevent_context.dox b/lib/tevent/doc/tevent_context.dox new file mode 100644 index 0000000..39eb85e --- /dev/null +++ b/lib/tevent/doc/tevent_context.dox @@ -0,0 +1,75 @@ +/** +@page tevent_context Chapter 1: Tevent context + +@section context Tevent context + +Tevent context is an essential logical unit of tevent library. For working with +events at least one such context has to be created - allocated, initialized. +Then, events which are meant to be caught and handled have to be registered +within this specific context. Reason for subordinating events to a tevent +context structure rises from the fact that several context can be created and +each of them is processed at different time. So, there can be 1 context +containing just file descriptor events, another one taking care of signal and +time events and the third one which keeps information about the rest. + +Tevent loops are the part of the library which represents the mechanism where +noticing events and triggering handlers actually happens. They accept just one +argument - tevent context structure. Therefore if theoretically an infinity +loop (tevent_loop_wait) was called, only those arguments which belong to the +passed tevent context structure can be caught and invoked within this call. +Although some more signal events were registered (but within some other +context) they will not be noticed. + +@subsection Example + +First lines which handle <code>mem_ctx</code> belong to talloc library +knowledge but because of the fact that tevent uses the talloc library for its +mechanisms it is necessary to understand a bit talloc as well. For more +information about working with talloc, please visit <a +href="http://talloc.samba.org/">talloc website</a> where tutorial and +documentation are located. + +Tevent context structure <code>*event_ctx</code> represents the unit which will +further contain information about registered events. It is created via calling +tevent_context_init(). + +@code +TALLOC_CTX *mem_ctx = talloc_new(NULL); +if (mem_ctx == NULL) { + // error handling +} + +struct tevent_context *ev_ctx = tevent_context_init(mem_ctx); +if(ev_ctx == NULL) { + // error handling +} +@endcode + +Tevent context has a structure containing lots of information. It include lists +of all events which are divided according their type and are in order showing +the sequence as they came. + +@image html tevent_context_stucture.png + +In addition to the lists shown in the diagram, the tevent context also contains +many other data (e.g. information about the available system mechanism for +triggering callbacks). + +@section tevent_loops Tevent loops + +Tevent loops are the dispatcher for events. They catch them and trigger the +handlers. In the case of longer processes, the program spends most of its time +at this point waiting for events, invoking handlers and waiting for another +event again. There are 2 types of loop available for use in tevent library: + +<ul> +<li>int tevent_loop_wait()</li> +<li>int tevent_loop_once()</li> +</ul> + +Both of functions accept just one parameter (tevent context) and the only +difference lies in the fact that the first loop can theoretically last for ever +but the second one will wait just for a single one event to catch and then the +loop breaks and the program continue. + +*/ diff --git a/lib/tevent/doc/tevent_data.dox b/lib/tevent/doc/tevent_data.dox new file mode 100644 index 0000000..dbe7a04 --- /dev/null +++ b/lib/tevent/doc/tevent_data.dox @@ -0,0 +1,137 @@ +/** +@page tevent_data Chapter 3: Accessing data +@section data Accessing data with tevent + +A tevent request is (usually) created together with a structure for storing the +data necessary for an asynchronous computation. For these private data, tevent +library uses void (generic) pointers, therefore any data type can be very +simply pointed at. However, this attitude requires clear and guaranteed +knowledge of the data type that will be handled, in advance. Private data can +be of 2 types: connected with a request itself or given as an individual +argument to a callback. It is necessary to differentiate these types, because +there is a slightly different method of data access for each. There are two +possibilities how to access data that is given as an argument directly to a +callback. The difference lies in the pointer that is returned. In one case it +is the data type specified in the function’s argument, in another void* is +returned. + +@code +void tevent_req_callback_data (struct tevent_req *req, #type) +void tevent_req_callback_data_void (struct tevent_req *req) +@endcode + + +To obtain data that are strictly bound to a request, this function is the only +direct procedure. + +@code +void *tevent_req_data (struct tevent_req *req, #type) +@endcode + +Example with both calls which differs between private data within tevent +request and data handed over as an argument. + +@code +#include <stdio.h> +#include <unistd.h> +#include <tevent.h> + +struct foo_state { + int x; +}; + +struct testA { + int y; +}; + + +static void foo_done(struct tevent_req *req) { + // a->x contains 10 since it came from foo_send + struct foo_state *a = tevent_req_data(req, struct foo_state); + + // b->y contains 9 since it came from run + struct testA *b = tevent_req_callback_data(req, struct testA); + + // c->y contains 9 since it came from run we just used a different way + // of getting it. + struct testA *c = (struct testA *)tevent_req_callback_data_void(req); + + printf("a->x: %d\n", a->x); + printf("b->y: %d\n", b->y); + printf("c->y: %d\n", c->y); +} + + +struct tevent_req * foo_send(TALLOC_CTX *mem_ctx, struct tevent_context *event_ctx) { + +printf("_send\n"); +struct tevent_req *req; +struct foo_state *state; + +req = tevent_req_create(event_ctx, &state, struct foo_state); +state->x = 10; + +return req; +} + +static void run(struct tevent_context *ev, struct tevent_timer *te, + struct timeval current_time, void *private_data) { + struct tevent_req *req; + struct testA *tmp = talloc(ev, struct testA); + + // Note that we did not use the private data passed in + + tmp->y = 9; + req = foo_send(ev, ev); + + tevent_req_set_callback(req, foo_done, tmp); + tevent_req_done(req); + +} + +int main (int argc, char **argv) { + + struct tevent_context *event_ctx; + struct testA *data; + TALLOC_CTX *mem_ctx; + struct tevent_timer *time_event; + + mem_ctx = talloc_new(NULL); //parent + if (mem_ctx == NULL) + return EXIT_FAILURE; + + event_ctx = tevent_context_init(mem_ctx); + if (event_ctx == NULL) + return EXIT_FAILURE; + + data = talloc(mem_ctx, struct testA); + data->y = 11; + + time_event = tevent_add_timer(event_ctx, + mem_ctx, + tevent_timeval_current(), + run, + data); + if (time_event == NULL) { + fprintf(stderr, " FAILED\n"); + return EXIT_FAILURE; + } + + tevent_loop_once(event_ctx); + + talloc_free(mem_ctx); + + printf("Quit\n"); + return EXIT_SUCCESS; +} +@endcode + +Output of this example is: + +@code +a->x: 10 +b->y: 9 +c->y: 9 +@endcode + +*/ diff --git a/lib/tevent/doc/tevent_events.dox b/lib/tevent/doc/tevent_events.dox new file mode 100644 index 0000000..d56af25 --- /dev/null +++ b/lib/tevent/doc/tevent_events.dox @@ -0,0 +1,341 @@ +/** +@page tevent_events Chapter 2: Tevent events +@section pools Tevent events + +Ok, after reading previous chapter we can start doing something useful. So, the +way of creating events is similar for all types - signals, file descriptors, +time or immediate events. At the beginning it is good to know about some +typedefs which are set in tevent library and which specify the arguments for +each callback. These callbacks are: + +- tevent_timer_handler_t() + +- tevent_immediate_handler_t() + +- tevent_signal_handler_t() + +- tevent_fd_handler_t() + +According their names it is obvious that for creating callback for e.g. time +event, tevent_timer_handler_t will be used. + +The best way how to introduce registering an event and setting up a callback +would be example, so examples describing all the types of events follow. + +@subsection Time Time event + +This example shows how to set up an event which will be repeated for a minute +with interval of 2 seconds (will be triggered 30 times). After exceeding this +limit, the event loop will finish and all the memory resources will be freed. +This is just example describing repeated activity, nothing usefull is done +within foo function + +@code +#include <stdio.h> +#include <unistd.h> +#include <tevent.h> +#include <sys/time.h> + +struct state { + struct timeval endtime; + int counter; + TALLOC_CTX *ctx; +}; + +static void callback(struct tevent_context *ev, struct tevent_timer *tim, + struct timeval current_time, void *private_data) +{ + struct state *data = talloc_get_type_abort(private_data, struct state); + struct tevent_timer *time_event; + struct timeval schedule; + + printf("Data value: %d\n", data->counter); + data->counter += 1; // increase counter + + // if time has not reached its limit, set another event + if (tevent_timeval_compare(¤t_time, &(data->endtime)) < 0) { + // do something + // set repeat with delay 2 seconds + schedule = tevent_timeval_current_ofs(2, 0); + time_event = tevent_add_timer(ev, data->ctx, schedule, callback, data); + if (time_event == NULL) { // error ... + fprintf(stderr, "MEMORY PROBLEM\n"); + return; + } + } else { + // time limit exceeded + } +} + +int main(void) { + struct tevent_context *event_ctx; + TALLOC_CTX *mem_ctx; + struct tevent_timer *time_event; + struct timeval schedule; + + mem_ctx = talloc_new(NULL); // parent + event_ctx = tevent_context_init(mem_ctx); + + struct state *data = talloc(mem_ctx, struct state); + + schedule = tevent_timeval_current_ofs(2, 0); // +2 second time value + data->endtime = tevent_timeval_add(&schedule, 60, 0); // one minute time limit + data->ctx = mem_ctx; + data->counter = 0; + + // add time event + time_event = tevent_add_timer(event_ctx, mem_ctx, schedule, callback, data); + if (time_event == NULL) { + fprintf(stderr, "FAILED\n"); + return EXIT_FAILURE; + } + + tevent_loop_wait(event_ctx); + talloc_free(mem_ctx); + return EXIT_SUCCESS; +} +@endcode + +Variable <code>counter</code> is only used for counting the number of triggered +functions. List of all available functions which tevent offers for working with +time are listed +<a href="http://tevent.samba.org/group__tevent__helpers.html">here</a> together +with their description. More detailed view at these functions is unnecessary +because their purpose and usage is quite simple and clear. + +@subsection Immediate Immediate event + +These events are, as their name indicates, activated and performed immediately. +It means that this kind of events have priority over others (except signal +events). So if there is a bulk of events registered and after that a +tevent loop is launched, then all the immediate events will be triggered before +the other events. Except other immediate events (and signal events) because +they are also processed sequentially - according the order they were scheduled. +Signals have the highest priority and therefore they are processed +preferentially. Therefore the expression immediate may not correspond exactly +to the dictionary definition of "something without delay" but rather "as soon +as possible" after all preceding immediate events. + +For creating an immediate event there is a small different which lies in the +fact that the creation of such event is done in 2 steps. One represents the +creation (memory allocation), the second one represents registering as the +event within some tevent context. + +@code +struct tevent_immediate *run(TALLOC_CTX* mem_ctx, + struct tevent_context event_ctx, + void * data) +{ + struct tevent_immediate *im; + + im = tevent_create_immediate(mem_ctx); + if (im == NULL) { + return NULL; + } + tevent_schedule_immediate(im, event_ctx, foo, data); + + return im; +} +@endcode + +Example which may be compiled and run representing the creation of immediate event. + +@code + +#include <stdio.h> +#include <unistd.h> +#include <tevent.h> + +struct info_struct { + int counter; +}; + +static void foo(struct tevent_context *ev, struct tevent_immediate *im, + void *private_data) +{ + struct info_struct *data = talloc_get_type_abort(private_data, struct info_struct); + printf("Data value: %d\n", data->counter); +} + +int main (void) { + struct tevent_context *event_ctx; + TALLOC_CTX *mem_ctx; + struct tevent_immediate *im; + + printf("INIT\n"); + + mem_ctx = talloc_new(NULL); + event_ctx = tevent_context_init(mem_ctx); + + struct info_struct *data = talloc(mem_ctx, struct info_struct); + + // setting up private data + data->counter = 1; + + // first immediate event + im = tevent_create_immediate(mem_ctx); + if (im == NULL) { + fprintf(stderr, "FAILED\n"); + return EXIT_FAILURE; + } + tevent_schedule_immediate(im, event_ctx, foo, data); + + tevent_loop_wait(event_ctx); + talloc_free(mem_ctx); + + return 0; +} +@endcode + +@subsection Signal Signal event + +This is an alternative to standard C library functions signal() or sigaction(). +The main difference that distinguishes these ways of treating signals is their +setting up of handlers for different time intervals of the running program. + +While standard C library methods for dealing with signals offer sufficient +tools for most cases, they are inadequate for handling signals within the +tevent loop. It could be necessary to finish certain tevent requests within the +tevent loop without interruption. If a signal was sent to a program at a moment +when the tevent loop is in progress, a standard signal handler would not return +processing to the application at the very same place and it would quit the +tevent loop for ever. In such cases, tevent signal handlers offer the +possibility of dealing with these signals by masking them from the rest of +application and not quitting the loop, so the other events can still be +processed. + +Tevent offers also a control function, which enables us to verify whether it is +possible to handle signals via tevent, is defined within tevent library and it +returns a boolean value revealing the result of the verification. + +@code +bool tevent_signal_support (struct tevent_context *ev) +@endcode + +Checking for signal support is not necessary, but if it is not guaranteed, this +is a good and easy control to prevent unexpected behaviour or failure of the +program occurring. Such a test of course does not have to be run every single +time you wish to create a signal handler, but simply at the beginning - during +the initialization procedures of the program. Afterthat, simply adapt to each +situation that arises. + +@code + +#include <stdio.h> +#include <tevent.h> +#include <signal.h> + +static void handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + + // Do something usefull + + printf("handling signal...\n"); + exit(EXIT_SUCCESS); +} + +int main (void) +{ + struct tevent_context *event_ctx; + TALLOC_CTX *mem_ctx; + struct tevent_signal *sig; + + mem_ctx = talloc_new(NULL); //parent + if (mem_ctx == NULL) { + fprintf(stderr, "FAILED\n"); + return EXIT_FAILURE; + } + + event_ctx = tevent_context_init(mem_ctx); + if (event_ctx == NULL) { + fprintf(stderr, "FAILED\n"); + return EXIT_FAILURE; + } + + if (tevent_signal_support(event_ctx)) { + // create signal event + sig = tevent_add_signal(event_ctx, mem_ctx, SIGINT, 0, handler, NULL); + if (sig == NULL) { + fprintf(stderr, "FAILED\n"); + return EXIT_FAILURE; + } + tevent_loop_wait(event_ctx); + } + + talloc_free(mem_ctx); + return EXIT_SUCCESS; +} +@endcode + + +@subsection File File descriptor event + +Support of events on file descriptors is mainly useful for socket communication +but it certainly works flawlessly with standard streams (stdin, stdout, stderr) + as well. Working asynchronously with file descriptors enables switching + within processing I/O operations. This ability may rise with a greater + number of I/O operations and such overlapping leads to enhancement of the + throughput. + +There are several other functions included in tevent API related to handling +file descriptors (there are too many functions defined within tevent therefore +just some of them are fully described within this thesis. The +declaration of the rest can be easily found on the library’s website or +directly from the source code): + +<ul> +<li>tevent_fd_set_close_fn() - can add another function to be called at the + moment when a structure tevent fd is freed.</li> +<li>tevent_fd_set_auto_close() - calling this function can simplify the + maintenance of file descriptors, because it instructs tevent to close the + appropriate file descriptor when the tevent fd structure is about to be + freed.</li> +<li>tevent_fd_get_flags() - returns flags which are set on the file descriptor + connected with this tevent fd structure.</li> +<li>tevent_fd_set_flags() - sets specified flags on the event’s file + descriptor.</li> +</ul> + +@code + +static void close_fd(struct tevent_context *ev, struct tevent_fd *fd_event, + int fd, void *private_data) +{ + // processing when fd_event is freed +} + +struct static void handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data) +{ + // handling event; reading from a file descriptor + tevent_fd_set_close_fn (fd_event, close_fd); +} + +int run(TALLOC_CTX *mem_ctx, struct tevent_context *event_ctx, + int fd, uint16_t flags, char *buffer) +{ + struct tevent_fd* fd_event = NULL; + + if (flags & TEVENT_FD_READ) { + fd_event = tevent_add_fd(event_ctx, + mem_ctx, + fd, + flags, + handler, + buffer); + } + if (fd_event == NULL) { + // error handling + } + return tevent_loop_once(); +} +@endcode + +*/ diff --git a/lib/tevent/doc/tevent_queue.dox b/lib/tevent/doc/tevent_queue.dox new file mode 100644 index 0000000..9c247e5 --- /dev/null +++ b/lib/tevent/doc/tevent_queue.dox @@ -0,0 +1,275 @@ +/** +@page tevent_queue Chapter 5: Tevent queue +@section queue Tevent queue + +There is a possibility that the dispatcher and its handlers may not be able to +handle all the incoming events as quickly as they arrive. One way to deal with +this situation is to buffer the received events by introducing an event queue +into the events stream, between the events generator and the dispatcher. Events +are added to the queue as they arrive, and the dispatcher pops them off the +beginning of the queue as fast as possible. In tevent library it is +similar, but the queue is not automatically set for any event. The queue has to +be created on purpose, and events which should follow the order of the FIFO +queue have to be explicitly pinpointed. Creating such a queue is crucial in +situations when sequential processing is absolutely essential for the +successful +completion of a task, e.g. for a large quantity of data that are about to be +written from a buffer into a socket. The tevent library has its own queue +structure that is ready to use after it has been initialized and started up +once. + +@subsection cr_queue Creation of Queues + +The first and most important step is the creation of the tevent queue +(represented by struct tevent_queue), which will then be in running mode. + +@code +struct tevent_queue* tevent_queue_create (TALLOC_CTX *mem_ctx, const char *name) +@endcode + +When the program returns from this function, the allocated memory, set +destructor and labeled queue as running has been done and the structure is +ready to be filled with entries. Stopping and starting queues on the run. If +you need to stop a queue from processing its entries, and then turn it on +again, a couple of functions which serve this purpose are: + +- bool tevent_queue_stop() +- bool tevent_queue_start() + +These functions actually only provide for the simple setting of a variable, +which indicates that the queue has been stopped/started. Returned value +indicates result. + +@subsection add_queue Adding Requests to a Queue + +Tevent in fact offers 3 possible ways of inserting a request into a queue. +There are no vast differences between them, but still there might be situations +where one of them is more suitable and desired than another. + +@code +bool tevent_queue_add(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data) +@endcode + +This call is the simplest of all three. It offers only boolean verification of +whether the operation of adding the request into a queue was successful or not. +No additional deletion of an item from the queue is possible, i.e. it is only +possible to deallocate the whole tevent request, which would cause triggering +of destructor handling and also dropping the request from the queue. + +<strong>Extended Options</strong> + +Both of the following functions have a feature in common - they return tevent +queue entry structure representing the item in a queue. There is no further +possible handling with this structure except the use of the structure’s pointer +for its deallocation (which leads also its removal from the queue). The +difference lies in the possibility that with the following functions it is +possible to remove the tevent request from a queue without its deallocation. +The previous function can only deallocate the tevent request as it was from +memory, and thereby logically cause its removal from the queue as well. There +is no other utilization of this structure via API at this stage of tevent +library. The possibility of easier debugging while developing with tevent could +be considered to be an advantage of this returned pointer. + +@code +struct tevent_queue_entry *tevent_queue_add_entry(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data) +@endcode + +The feature that allows for the optimized addition of entries to a queue is +that a check for an empty queue with no items is first of all carried out. If +it is found that the queue is empty, then the request for inserting the entry +into a queue will be omitted and directly triggered. + +@code +struct tevent_queue_entry *tevent_queue_add_optimize_empty(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data) +@endcode + +When calling any of the functions serving for inserting an item into a queue, +it is possible to leave out the fourth argument (trigger) and instead of a +function pass a NULL pointer. This usage sets so-called blocking entries. +These entries, since they do not have any trigger operation to be activated, +just sit in their position until they are labeled as a done by another +function. Their purpose is to block other items in the queue from being +triggered. + +@subsection example_q Example of tevent queue + +@code +#include <stdio.h> +#include <unistd.h> +#include <tevent.h> + +struct foo_state { + int local_var; + int x; +}; + +struct juststruct { + TALLOC_CTX * ctx; + struct tevent_context *ev; + int y; +}; + +int created = 0; + +static void timer_handler(struct tevent_context *ev, struct tevent_timer *te, + struct timeval current_time, void *private_data) +{ + // time event which after all sets request as done. Following item from + // the queue may be invoked. + struct tevent_req *req = private_data; + struct foo_state *stateX = tevent_req_data(req, struct foo_state); + + // processing some stuff + + printf("time_handler\n"); + + tevent_req_done(req); + talloc_free(req); + + printf("Request #%d set as done.\n", stateX->x); +} + +static void trigger(struct tevent_req *req, void *private_data) +{ + struct juststruct *priv = tevent_req_callback_data (req, struct juststruct); + struct foo_state *in = tevent_req_data(req, struct foo_state); + struct timeval schedule; + struct tevent_timer *tim; + schedule = tevent_timeval_current_ofs(1, 0); + printf("Processing request #%d\n", in->x); + + if (in->x % 3 == 0) { // just example; third request does not contain + // any further operation and will be finished right + // away. + tim = NULL; + } else { + tim = tevent_add_timer(priv->ev, req, schedule, timer_handler, req); + } + + if (tim == NULL) { + tevent_req_done(req); + talloc_free(req); + printf("Request #%d set as done.\n", in->x); + } +} + +struct tevent_req *foo_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, + const char *name, int num) +{ + struct tevent_req *req; + struct foo_state *state; + struct foo_state *in; + struct tevent_timer *tim; + + printf("foo_send\n"); + req = tevent_req_create(mem_ctx, &state, struct foo_state); + if (req == NULL) { // check for appropriate allocation + tevent_req_error(req, 1); + return NULL; + } + + // exemplary filling of variables + state->local_var = 1; + state->x = num; + + return req; +} + +static void foo_done(struct tevent_req *req) { + + enum tevent_req_state state; + uint64_t err; + + if (tevent_req_is_error(req, &state, &err)) { + printf("ERROR WAS SET %d\n", state); + return; + } else { + // processing some stuff + printf("Callback is done...\n"); + } +} + +int main (int argc, char **argv) +{ + TALLOC_CTX *mem_ctx; + struct tevent_req* req[6]; + struct tevent_req* tmp; + struct tevent_context *ev; + struct tevent_queue *fronta = NULL; + struct juststruct *data; + int ret; + int i = 0; + + const char * const names[] = { + "first", "second", "third", "fourth", "fifth" + }; + + printf("INIT\n"); + + mem_ctx = talloc_new(NULL); //parent + talloc_parent(mem_ctx); + ev = tevent_context_init(mem_ctx); + if (ev == NULL) { + fprintf(stderr, "MEMORY ERROR\n"); + return EXIT_FAILURE; + } + + // setting up queue + fronta = tevent_queue_create(mem_ctx, "test_queue"); + tevent_queue_stop(fronta); + tevent_queue_start(fronta); + if (tevent_queue_running(fronta)) { + printf ("Queue is runnning (length: %d)\n", tevent_queue_length(fronta)); + } else { + printf ("Queue is not runnning\n"); + } + + data = talloc(ev, struct juststruct); + data->ctx = mem_ctx; + data->ev = ev; + + + // create 4 requests + for (i = 1; i < 5; i++) { + req[i] = foo_send(mem_ctx, ev, names[i], i); + tmp = req[i]; + if (req[i] == NULL) { + fprintf(stderr, "Request error! %d \n", ret); + break; + } + tevent_req_set_callback(req[i], foo_done, data); + created++; + } + + // add item to a queue + tevent_queue_add(fronta, ev, req[1], trigger, data); + tevent_queue_add(fronta, ev, req[2], trigger, data); + tevent_queue_add(fronta, ev, req[3], trigger, data); + tevent_queue_add(fronta, ev, req[4], trigger, data); + + printf("Queue length: %d\n", tevent_queue_length(fronta)); + while(tevent_queue_length(fronta) > 0) { + tevent_loop_once(ev); + printf("Queue: %d items left\n", tevent_queue_length(fronta)); + } + + talloc_free(mem_ctx); + printf("FINISH\n"); + + return EXIT_SUCCESS; +} +@endcode + +*/ diff --git a/lib/tevent/doc/tevent_request.dox b/lib/tevent/doc/tevent_request.dox new file mode 100644 index 0000000..e1e45b1 --- /dev/null +++ b/lib/tevent/doc/tevent_request.dox @@ -0,0 +1,189 @@ +/** +@page tevent_request Chapter 4: Tevent request +@section request Tevent request + +A specific feature of the library is the tevent request API that provides for +asynchronous computation and allows much more interconnected working and +cooperation among functions and events. When working with tevent request it +is possible to nest one event under another and handle them bit by bit. This +enables the creation of sequences of steps, and provides an opportunity to +prepare for all problems which may unexpectedly happen within the different +phases. One way or another, subrequests split bigger tasks into smaller ones +which allow a clearer view of each task as a whole. + +@subsection name Naming conventions + +There is a naming convention which is not obligatory but it is followed in this +tutorial: + +- Functions triggered before the event happens. These establish a request. +- \b foo_send(...) - this function is called first and it includes the + creation of tevent request - tevent req structure. It does not block + anything, it simply creates a request, sets a callback (foo done) and lets + the program continue +- Functions as a result of event. +- \b foo_done(...) - this function contains code providing for handling itself + and based upon its results, the request is set either as a done or, if an + error occurs, the request is set as a failure. +- \b foo_recv(...) - this function contains code which should, if demanded, + access the result data and make them further visible. The foo state should + be deallocated from memory when the request’s processing is over and + therefore all computed data up to this point would be lost. + +As was already mentioned, specific naming subsumes not only functions but also +the data themselves: + +- \b foo_state - this is a structure. It contains all the data necessary for + the asynchronous task. + +@subsection cr_req Creating a New Asynchronous Request + +The first step for working asynchronously is the allocation of memory +requirements. As in previous cases, the talloc context is required, upon which +the asynchronous request will be tied. The next step is the creation of the +request itself. + +@code +struct tevent_req* tevent_req_create (TALLOC_CTX *mem_ctx, void **pstate, #type) +@endcode + +The pstate is the pointer to the private data. The necessary amount of memory +(based on data type) is allocated during this call. Within this same memory +area all the data from the asynchronous request that need to be preserved for +some time should be kept. + +<b>Dealing with a lack of memory</b> + +The verification of the returned pointer against NULL is necessary in order to +identify a potential lack of memory. There is a special function which helps +with this check tevent_req_nomem(). + +It handles verification both of the talloc memory allocation and of the +associated tevent request, and is therefore a very useful function for avoiding +unexpected situations. It can easily be used when checking the availability of +further memory resources that are required for a tevent request. Imagine an +example where additional memory needs arise although no memory resources are +currently available. + +@code +bar = talloc(mem_ctx, struct foo); +if(tevent_req_nomem (bar, req)) { + // handling a problem +} +@endcode + +This code ensures that the variable bar, which contains NULL as a result of the +unsuccessful satisfaction of its memory requirements, is noticed, and also that +the tevent request req declares it exceeds memory capacity, which implies the +impossibility of finishing the request as originally programmed. + + +@subsection fini_req Finishing a Request + +Marking each request as finished is an essential principle of the tevent +library. Without marking the request as completed - either successfully or with +an error - the tevent loop could not let the appropriate callback be triggered. +It is important to understand that this would be a significant threat, because +it is not usually a question of one single function which prints some text on a +screen, but rather the request is itself probably just a link in a series of +other requests. Stopping one request would stop the others, memory resources +would not be freed, file descriptors might remain open, communication via +socket could be interrupted, and so on. Therefore it is important to think +about finishing requests, either successfully or not, and also to prepare +functions for all possible scenarios, so that the the callbacks do not process +data that are actually invalid or, even worse, in fact non-existent meaning +that a segmentation fault may arise. + +<ul> +<li>\b Manually - This is the most common type of finishing request. Calling +this function sets the request as a TEVENT_REQ_DONE. This is the only purpose +of this function and it should be used when everything went well. Typically it +is used within the done functions. + +@code +void tevent_req_done (struct tevent_req *req) +@endcode +Alternatively, the request can end up being unsuccessful. +@code +bool tevent_req_error (struct tevent_req *req, uint64_t error) +@endcode + +The second argument takes the number of an error (declared by the programmer, +for example in an enumerated variable). The function tevent_req_error() sets +the status of the request as a TEVENT_REQ_USER_ERROR and also stores the code +of error within the structure so it can be used, for example for debugging. The +function returns true, if marking the request as an error was processed with no +problem - value error passed to this function is not equal to 1.</li> + +<li> +<b>Setting up a timeout for request</b> - A request can be finished virtually, +or if the process takes too much time, it can be timed out. This is considered +as an error of the request and it leads to calling callback. In the +background, this timeout is set through a time event (described in +@subpage tevent_events ) which eventually triggers an operation marking the +request as a TEVENT_REQ_TIMED_OUT (can not be considered as successfully +finished). In case a time out was already set, this operation will overwrite it +with a new time value (so the timeout may be lengthened) and if everything is +set properly, it returns true. + +@code +bool tevent_req_set_endtime(struct tevent_req *req, + struct tevent_context *ev, + struct timeval endtime); +@endcode +</li> + + +<li><b>Premature Triggering</b> - Imagine a situation in which some part of a +nested subrequest ended up with a failure and it is still required to trigger a +callback. Such as example might result from lack of memory leading to the +impossibility of allocating enough memory requirements for the event to start +processing another subrequest, or from a clear intention to skip other +procedures and trigger the callback regardless of other progress. In these +cases, the function tevent_req_post() is very handy and offers this option. + +@code +struct tevent_req* tevent_req_post (struct tevent_req *req, + struct tevent_context *ev); +@endcode + +A request finished in this way does not behave as a time event nor as a file +descriptor event but as a immediately scheduled event, and therefore it will be +treated according the description laid down in @subpage tevent_events . +</li> +</ul> + + +@section nested Subrequests - Nested Requests + +To create more complex and interconnected asynchronous operations, it is +possible to submerge a request into another and thus create a so-called +subrequest. Subrequests are not represented by any other special structure but +they are created from tevent_req_create(). This diagram shows the nesting and +life time of each request. The table below describes the same in words, and +shows the triggering of functions during the application run. + +<i>Wrapper</i> represents the trigger of the whole cascade of (sub)requests. It +may be e.g. a time or file descriptor event, or another request that was +created at a specific time by the function tevent_wakeup_send() which is a +slightly exceptional method of creating + +@code +struct tevent_req *tevent_wakeup_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct timeval wakeup_time); +@endcode + +By calling this function, it is possible to create a tevent request which is +actually the return value of this function. In summary, it sets the time value +of the tevent request’s creation. While using this function it is necessary to +use another function in the subrequest’s callback to check for any problems +tevent_wakeup_recv() ) + +@image html tevent_subrequest.png + +A comprehensive example of nested subrequests can be found in the file +echo_server.c. It implements a complete, self-contained echo server with no +dependencies but libevent and libtalloc. + +*/ diff --git a/lib/tevent/doc/tevent_thread.dox b/lib/tevent/doc/tevent_thread.dox new file mode 100644 index 0000000..875dae8 --- /dev/null +++ b/lib/tevent/doc/tevent_thread.dox @@ -0,0 +1,322 @@ +/** +@page tevent_thread Chapter 6: Tevent with threads + +@section threads Tevent with threads + +In order to use tevent with threads, you must first understand +how to use the talloc library in threaded programs. For more +information about working with talloc, please visit <a +href="https://talloc.samba.org/">talloc website</a> where tutorial and +documentation are located. + +If a tevent context structure is talloced from a NULL, thread-safe talloc +context, then it can be safe to use in a threaded program. The function +<code>talloc_disable_null_tracking()</code> <b>must</b> be called from the initial +program thread before any talloc calls are made to ensure talloc is thread-safe. + +Each thread must create it's own tevent context structure as follows +<code>tevent_context_init(NULL)</code> and no talloc memory contexts +can be shared between threads. + +Separate threads using tevent in this way can communicate +by writing data into file descriptors that are being monitored +by a tevent context on another thread. For example (simplified +with no error handling): + +@code +Main thread: + +main() +{ + talloc_disable_null_tracking(); + + struct tevent_context *master_ev = tevent_context_init(NULL); + void *mem_ctx = talloc_new(master_ev); + + // Create file descriptor to monitor. + int pipefds[2]; + + pipe(pipefds); + + struct tevent_fd *fde = tevent_add_fd(master_ev, + mem_ctx, + pipefds[0], // read side of pipe + TEVENT_FD_READ, + pipe_read_handler, // callback function + private_data_pointer); + + // Create sub thread, pass pipefds[1] write side of pipe to it. + // The above code not shown here.. + + // Process events. + tevent_loop_wait(master_ev); + + // Cleanup if loop exits. + talloc_free(master_ev); +} + +@endcode + +When the subthread writes to pipefds[1], the function +<code>pipe_read_handler()</code> will be called in the main thread. + +@subsection More sophisticated use + +A popular way to use an event library within threaded programs +is to allow a sub-thread to asynchronously schedule a tevent_immediate +function call from the event loop of another thread. This can be built +out of the basic functions and isolation mechanisms of tevent, +but tevent also comes with some utility functions that make +this easier, so long as you understand the limitations that +using threads with talloc and tevent impose. + +To allow a tevent context to receive an asynchronous tevent_immediate +function callback from another thread, create a struct tevent_thread_proxy * +by calling @code + +struct tevent_thread_proxy *tevent_thread_proxy_create( + struct tevent_context *dest_ev_ctx); + +@endcode + +This function allocates the internal data structures to +allow asynchronous callbacks as a talloc child of the +struct tevent_context *, and returns a struct tevent_thread_proxy * +that can be passed to another thread. + +When you have finished receiving asynchronous callbacks, simply +talloc_free the struct tevent_thread_proxy *, or talloc_free +the struct tevent_context *, which will deallocate the resources +used. + +To schedule an asynchronous tevent_immediate function call from one +thread on the tevent loop of another thread, use +@code + +void tevent_thread_proxy_schedule(struct tevent_thread_proxy *tp, + struct tevent_immediate **pp_im, + tevent_immediate_handler_t handler, + void **pp_private_data); + +@endcode + +This function causes the function <code>handler()</code> +to be invoked as a tevent_immediate callback from the event loop +of the thread that created the struct tevent_thread_proxy * +(so the owning <code>struct tevent_context *</code> should be +long-lived and not in the process of being torn down). + +The <code>struct tevent_thread_proxy</code> object being +used here is a child of the event context of the target +thread. So external synchronization mechanisms must be +used to ensure that the target object is still in use +at the time of the <code>tevent_thread_proxy_schedule()</code> +call. In the example below, the request/response nature +of the communication ensures this. + +The <code>struct tevent_immediate **pp_im</code> passed into this function +should be a struct tevent_immediate * allocated on a talloc context +local to this thread, and will be reparented via talloc_move +to be owned by <code>struct tevent_thread_proxy *tp</code>. +<code>*pp_im</code> will be set to NULL on successful scheduling +of the tevent_immediate call. + +<code>handler()</code> will be called as a normal tevent_immediate +callback from the <code>struct tevent_context *</code> of the destination +event loop that created the <code>struct tevent_thread_proxy *</code> + +Returning from this functions does not mean that the <code>handler</code> +has been invoked, merely that it has been scheduled to be called in the +destination event loop. + +Because the calling thread does not wait for the +callback to be scheduled and run on the destination +thread, this is a fire-and-forget call. If you wish +confirmation of the <code>handler()</code> being +successfully invoked, you must ensure it replies to the +caller in some way. + +Because of asynchronous nature of this call, the nature +of the parameter passed to the destination thread has some +restructions. If you don't need parameters, merely pass +<code>NULL</code> as the value of +<code>void **pp_private_data</code>. + +If you wish to pass a pointer to data between the threads, +it <b>MUST</b> be a pointer to a talloced pointer, which is +not part of a talloc-pool, and it must not have a destructor +attached. The ownership of the memory pointed to will +be passed from the calling thread to the tevent library, +and if the receiving thread does not talloc-reparent +it to its own contexts, it will be freed once the +<code>handler</code> is called. + +On success, <code>*pp_private</code> will be <code>NULL</code> +to signify the talloc memory ownership has been moved. + +In practice for message passing between threads in +event loops these restrictions are not very onerous. + +The easiest way to to a request-reply pair between +tevent loops on different threads is to pass the +parameter block of memory back and forth using +a reply <code>tevent_thread_proxy_schedule()</code> +call. + +Here is an example (without error checking for +simplicity): + +@code +------------------------------------------------ +// Master thread. + +main() +{ + // Make talloc thread-safe. + + talloc_disable_null_tracking(); + + // Create the master event context. + + struct tevent_context *master_ev = tevent_context_init(NULL); + + // Create the master thread proxy to allow it to receive + // async callbacks from other threads. + + struct tevent_thread_proxy *master_tp = + tevent_thread_proxy_create(master_ev); + + // Create sub-threads, passing master_tp in + // some way to them. + // This code not shown.. + + // Process events. + // Function master_callback() below + // will be invoked on this thread on + // master_ev event context. + + tevent_loop_wait(master_ev); + + // Cleanup if loop exits. + + talloc_free(master_ev); +} + +// Data passed between threads. +struct reply_state { + struct tevent_thread_proxy *reply_tp; + pthread_t thread_id; + bool *p_finished; +}; + +// Callback Called in child thread context. + +static void thread_callback(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_ptr) +{ + // Move the ownership of what private_ptr + // points to from the tevent library back to this thread. + + struct reply_state *rsp = + talloc_get_type_abort(private_ptr, struct reply_state); + + talloc_steal(ev, rsp); + + *rsp->p_finished = true; + + // im will be talloc_freed on return from this call. + // but rsp will not. +} + +// Callback Called in master thread context. + +static void master_callback(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_ptr) +{ + // Move the ownership of what private_ptr + // points to from the tevent library to this thread. + + struct reply_state *rsp = + talloc_get_type_abort(private_ptr, struct reply_state); + + talloc_steal(ev, rsp); + + printf("Callback from thread %s\n", thread_id_to_string(rsp->thread_id)); + + /* Now reply to the thread ! */ + tevent_thread_proxy_schedule(rsp->reply_tp, + &im, + thread_callback, + &rsp); + + // Note - rsp and im are now NULL as the tevent library + // owns the memory. +} + +// Child thread. + +static void *thread_fn(void *private_ptr) +{ + struct tevent_thread_proxy *master_tp = + talloc_get_type_abort(private_ptr, struct tevent_thread_proxy); + bool finished = false; + int ret; + + // Create our own event context. + + struct tevent_context *ev = tevent_context_init(NULL); + + // Create the local thread proxy to allow us to receive + // async callbacks from other threads. + + struct tevent_thread_proxy *local_tp = + tevent_thread_proxy_create(master_ev); + + // Setup the data to send. + + struct reply_state *rsp = talloc(ev, struct reply_state); + + rsp->reply_tp = local_tp; + rsp->thread_id = pthread_self(); + rsp->p_finished = &finished; + + // Create the immediate event to use. + + struct tevent_immediate *im = tevent_create_immediate(ev); + + // Call the master thread. + + tevent_thread_proxy_schedule(master_tp, + &im, + master_callback, + &rsp); + + // Note - rsp and im are now NULL as the tevent library + // owns the memory. + + // Wait for the reply. + + while (!finished) { + tevent_loop_once(ev); + } + + // Cleanup. + + talloc_free(ev); + return NULL; +} + +@endcode + +Note this doesn't have to be a master-subthread communication. +Any thread that has access to the <code>struct tevent_thread_proxy *</code> +pointer of another thread that has called <code>tevent_thread_proxy_create() +</code> can send an async tevent_immediate request. + +But remember the caveat that external synchronization must be used +to ensure the target <code>struct tevent_thread_proxy *</code> object +exists at the time of the <code>tevent_thread_proxy_schedule()</code> +call or unreproducible crashes will result. +*/ diff --git a/lib/tevent/doc/tevent_tutorial.dox b/lib/tevent/doc/tevent_tutorial.dox new file mode 100644 index 0000000..207a244 --- /dev/null +++ b/lib/tevent/doc/tevent_tutorial.dox @@ -0,0 +1,22 @@ +/** +@page tevent_tutorial The Tutorial + +@section tevent_tutorial_introduction Introduction + +Tutorial describing working with tevent library. + +@section tevent_tutorial_toc Table of contents + +@subpage tevent_context + +@subpage tevent_events + +@subpage tevent_data + +@subpage tevent_request + +@subpage tevent_queue + +@subpage tevent_thread + +*/ diff --git a/lib/tevent/doc/tutorials.dox b/lib/tevent/doc/tutorials.dox new file mode 100644 index 0000000..e8beed7 --- /dev/null +++ b/lib/tevent/doc/tutorials.dox @@ -0,0 +1,43 @@ +/** + * @page tevent_queue_tutorial The tevent_queue tutorial + * + * @section Introduction + * + * A tevent_queue is used to queue up async requests that must be + * serialized. For example writing buffers into a socket must be + * serialized. Writing a large lump of data into a socket can require + * multiple write(2) or send(2) system calls. If more than one async + * request is outstanding to write large buffers into a socket, every + * request must individually be completed before the next one begins, + * even if multiple syscalls are required. + * + * To do this, every socket gets assigned a tevent_queue struct. + * + * Creating a serialized async request follows the usual convention to + * return a tevent_req structure with an embedded state structure. To + * serialize the work the requests is about to so, instead of directly + * starting or doing that work, tevent_queue_add must be called. When it + * is time for the serialized async request to do its work, the trigger + * callback function tevent_queue_add was given is called. In the example + * of writing to a socket, the trigger is called when the write request + * can begin accessing the socket. + * + * How does this engine work behind the scenes? When the queue is empty, + * tevent_queue_add schedules an immediate call to the trigger + * callback. The trigger callback starts its work, likely by starting + * other async subrequests. While these async subrequests are working, + * more requests can accumulate in the queue by tevent_queue_add. While + * there is no function to explicitly trigger the next waiter in line, it + * still works: When the active request in the queue is done, it will be + * destroyed by talloc_free. Talloc_free of an serialized async request + * that had been added to a queue will trigger the next request in the + * queue via a talloc destructor attached to a child of the serialized + * request. This way the queue will be kept busy when an async request + * finishes. + * + * @section Example + * + * @code + * Metze: Please add a code example here. + * @endcode + */ diff --git a/lib/tevent/doxy.config b/lib/tevent/doxy.config new file mode 100644 index 0000000..76d8b4c --- /dev/null +++ b/lib/tevent/doxy.config @@ -0,0 +1,1908 @@ +# Doxyfile 1.8.4 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed +# in front of the TAG it is preceding . +# All text after a hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" "). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = tevent + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = 0.9.8 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = doc + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Latvian, Lithuanian, Norwegian, Macedonian, +# Persian, Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, +# Slovak, Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. Note that you specify absolute paths here, but also +# relative paths, which will be relative from the directory where doxygen is +# started. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, +# and language is one of the parsers supported by doxygen: IDL, Java, +# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, +# C++. For instance to make doxygen treat .inc files as Fortran files (default +# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note +# that for custom extensions you also need to set FILE_PATTERNS otherwise the +# files are not read by doxygen. + +EXTENSION_MAPPING = + +# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all +# comments according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you +# can mix doxygen, HTML, and XML commands with Markdown formatting. +# Disable only in case of backward compatibilities issues. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES (the +# default) will make doxygen replace the get and set methods by a property in +# the documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields or simple typedef fields will be shown +# inline in the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO (the default), structs, classes, and unions are shown on a separate +# page (for HTML and Man pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can +# be an expensive process and often the same symbol appear multiple times in +# the code, doxygen keeps a cache of pre-resolved symbols. If the cache is too +# small doxygen will become slower. If the cache is too large, memory is wasted. +# The cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid +# range is 0..9, the default is 0, corresponding to a cache size of 2^16 = 65536 +# symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = NO + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if section-label ... \endif +# and \cond section-label ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command <command> <input-file>, where <command> is the value of +# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. Do not use +# file names with spaces, bibtex cannot handle them. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = . \ + doc + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.cpp \ + *.cc \ + *.c \ + *.h \ + *.hh \ + *.hpp \ + *.dox + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +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 +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = doc/img + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command <filter> <input-file>, where <filter> +# is the value of the INPUT_FILTER tag, and <input-file> is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be ignored. +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C, C++ and Fortran comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If left blank doxygen will +# generate a default style sheet. Note that it is recommended to use +# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this +# tag will in the future become obsolete. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional +# user-defined cascading style sheet that is included after the standard +# style sheets created by doxygen. Using this option one can overrule +# certain style aspects. This is preferred over using HTML_STYLESHEET +# since it does not replace the standard style sheet and is therefor more +# robust against future updates. Doxygen will copy the style sheet file to +# the output directory. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of +# entries shown in the various tree structured indices initially; the user +# can expand and collapse entries dynamically later on. Doxygen will expand +# the tree to such a level that at most the specified number of entries are +# visible (unless a fully collapsed tree already exceeds this amount). +# So setting the number of entries 1 will produce a full collapsed tree by +# default. 0 is a special value representing an infinite number of entries +# and will result in a full expanded tree by default. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely +# identify the documentation publisher. This should be a reverse domain-name +# style string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> +# Qt Help Project / Custom Filters</a>. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> +# Qt Help Project / Filter Attributes</a>. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. + +GENERATE_TREEVIEW = NONE + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you may also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and +# SVG. The default value is HTML-CSS, which is slower, but has the best +# compatibility. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to +# the MathJax Content Delivery Network so you can quickly see the result without +# installing MathJax. +# However, it is strongly recommended to install a local +# copy of MathJax from http://www.mathjax.org before deployment. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript +# pieces of code that will be used on startup of the MathJax code. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = NO + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a web server instead of a web client using Javascript. +# There are two flavours of web server based search depending on the +# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for +# searching and an index file used by the script. When EXTERNAL_SEARCH is +# enabled the indexing and searching needs to be provided by external tools. +# See the manual for details. + +SERVER_BASED_SEARCH = NO + +# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP +# script for searching. Instead the search results are written to an XML file +# which needs to be processed by an external indexer. Doxygen will invoke an +# external search engine pointed to by the SEARCHENGINE_URL option to obtain +# the search results. Doxygen ships with an example indexer (doxyindexer) and +# search engine (doxysearch.cgi) which are based on the open source search +# engine library Xapian. See the manual for configuration details. + +EXTERNAL_SEARCH = NO + +# The SEARCHENGINE_URL should point to a search engine hosted by a web server +# which will returned the search results when EXTERNAL_SEARCH is enabled. +# Doxygen ships with an example search engine (doxysearch) which is based on +# the open source search engine library Xapian. See the manual for configuration +# details. + +SEARCHENGINE_URL = + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed +# search data is written to a file for indexing by an external tool. With the +# SEARCHDATA_FILE tag the name of this file can be specified. + +SEARCHDATA_FILE = searchdata.xml + +# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the +# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is +# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple +# projects and redirect the results back to the right project. + +EXTERNAL_SEARCH_ID = + +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen +# projects other than the one defined by this configuration file, but that are +# all added to the same external search index. Each project needs to have a +# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id +# of to a relative location where the documentation can be found. +# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ... + +EXTRA_SEARCH_MAPPINGS = + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4 will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images +# or other source files which should be copied to the LaTeX output directory. +# Note that the files will be copied as-is; there are no commands or markers +# available. + +LATEX_EXTRA_FILES = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = YES + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- + +# If the GENERATE_DOCBOOK tag is set to YES Doxygen will generate DOCBOOK files +# that can be used to generate PDF. + +GENERATE_DOCBOOK = NO + +# The DOCBOOK_OUTPUT tag is used to specify where the DOCBOOK pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in +# front of it. If left blank docbook will be used as the default path. + +DOCBOOK_OUTPUT = docbook + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = YES + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = DOXYGEN \ + PRINTF_ATTRIBUTE(x,y)= + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. For each +# tag file the location of the external documentation should be added. The +# format of a tag file without this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths +# or URLs. Note that each tag file must have a unique name (where the name does +# NOT include the path). If a tag file is not located in the directory in which +# doxygen is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed +# in the related pages index. If set to NO, only the current project's +# pages will be listed. + +EXTERNAL_PAGES = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside +# the class node. If there are many fields or methods and many nodes the +# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS +# threshold limits the number of items for each type to make the size more +# manageable. Set this to 0 for no limit. Note that the threshold may be +# exceeded by 50% before the limit is enforced. + +UML_LIMIT_NUM_FIELDS = 10 + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = YES + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/lib/tevent/echo_server.c b/lib/tevent/echo_server.c new file mode 100644 index 0000000..f93d8bc --- /dev/null +++ b/lib/tevent/echo_server.c @@ -0,0 +1,667 @@ +/** + ** NOTE! The following liberal license applies to this sample file only. + ** This does NOT imply that all of Samba is released under this license. + ** + ** This file is meant as a starting point for libtevent users to be used + ** in any program linking against the LGPL licensed libtevent. + **/ + +/* + * This file is being made available by the Samba Team under the following + * license: + * + * Permission to use, copy, modify, and distribute this sample file for any + * purpose is hereby granted without fee. + * + * This work 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. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <netinet/in.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <errno.h> +#include <unistd.h> +#include "tevent.h" +#include "talloc.h" + +/** + * @brief Helper function to get a useful unix error from tevent_req + */ + +static bool tevent_req_is_unix_error(struct tevent_req *req, int *perrno) +{ + enum tevent_req_state state; + uint64_t err; + + if (!tevent_req_is_error(req, &state, &err)) { + return false; + } + switch (state) { + case TEVENT_REQ_TIMED_OUT: + *perrno = ETIMEDOUT; + break; + case TEVENT_REQ_NO_MEMORY: + *perrno = ENOMEM; + break; + case TEVENT_REQ_USER_ERROR: + *perrno = err; + break; + default: + *perrno = EINVAL; + break; + } + return true; +} + +/** + * @brief Wrapper around accept(2) + */ + +struct accept_state { + struct tevent_fd *fde; + int listen_sock; + socklen_t addrlen; + struct sockaddr_storage addr; + int sock; +}; + +static void accept_handler(struct tevent_context *ev, struct tevent_fd *fde, + uint16_t flags, void *private_data); + +static struct tevent_req *accept_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int listen_sock) +{ + struct tevent_req *req; + struct accept_state *state; + + req = tevent_req_create(mem_ctx, &state, struct accept_state); + if (req == NULL) { + return NULL; + } + + state->listen_sock = listen_sock; + + state->fde = tevent_add_fd(ev, state, listen_sock, TEVENT_FD_READ, + accept_handler, req); + if (tevent_req_nomem(state->fde, req)) { + return tevent_req_post(req, ev); + } + return req; +} + +static void accept_handler(struct tevent_context *ev, struct tevent_fd *fde, + uint16_t flags, void *private_data) +{ + struct tevent_req *req = talloc_get_type_abort( + private_data, struct tevent_req); + struct accept_state *state = tevent_req_data(req, struct accept_state); + int ret; + + TALLOC_FREE(state->fde); + + if ((flags & TEVENT_FD_READ) == 0) { + tevent_req_error(req, EIO); + return; + } + state->addrlen = sizeof(state->addr); + + ret = accept(state->listen_sock, + (struct sockaddr *)&state->addr, + &state->addrlen); + if (ret == -1) { + tevent_req_error(req, errno); + return; + } + smb_set_close_on_exec(ret); + state->sock = ret; + tevent_req_done(req); +} + +static int accept_recv(struct tevent_req *req, struct sockaddr *paddr, + socklen_t *paddrlen, int *perr) +{ + struct accept_state *state = tevent_req_data(req, struct accept_state); + int err; + + if (tevent_req_is_unix_error(req, &err)) { + if (perr != NULL) { + *perr = err; + } + return -1; + } + if (paddr != NULL) { + memcpy(paddr, &state->addr, state->addrlen); + } + if (paddrlen != NULL) { + *paddrlen = state->addrlen; + } + return state->sock; +} + +/** + * @brief Wrapper around read(2) + */ + +struct read_state { + struct tevent_fd *fde; + int fd; + void *buf; + size_t count; + + ssize_t nread; +}; + +static void read_handler(struct tevent_context *ev, struct tevent_fd *fde, + uint16_t flags, void *private_data); + +static struct tevent_req *read_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd, void *buf, size_t count) +{ + struct tevent_req *req; + struct read_state *state; + + req = tevent_req_create(mem_ctx, &state, struct read_state); + if (req == NULL) { + return NULL; + } + + state->fd = fd; + state->buf = buf; + state->count = count; + + state->fde = tevent_add_fd(ev, state, fd, TEVENT_FD_READ, + read_handler, req); + if (tevent_req_nomem(state->fde, req)) { + return tevent_req_post(req, ev); + } + return req; +} + +static void read_handler(struct tevent_context *ev, struct tevent_fd *fde, + uint16_t flags, void *private_data) +{ + struct tevent_req *req = talloc_get_type_abort( + private_data, struct tevent_req); + struct read_state *state = tevent_req_data(req, struct read_state); + ssize_t ret; + + TALLOC_FREE(state->fde); + + if ((flags & TEVENT_FD_READ) == 0) { + tevent_req_error(req, EIO); + return; + } + + ret = read(state->fd, state->buf, state->count); + if (ret == -1) { + tevent_req_error(req, errno); + return; + } + state->nread = ret; + tevent_req_done(req); +} + +static ssize_t read_recv(struct tevent_req *req, int *perr) +{ + struct read_state *state = tevent_req_data(req, struct read_state); + int err; + + if (tevent_req_is_unix_error(req, &err)) { + if (perr != NULL) { + *perr = err; + } + return -1; + } + return state->nread; +} + +/** + * @brief Wrapper around write(2) + */ + +struct write_state { + struct tevent_fd *fde; + int fd; + const void *buf; + size_t count; + + ssize_t nwritten; +}; + +static void write_handler(struct tevent_context *ev, struct tevent_fd *fde, + uint16_t flags, void *private_data); + +static struct tevent_req *write_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd, const void *buf, size_t count) +{ + struct tevent_req *req; + struct write_state *state; + + req = tevent_req_create(mem_ctx, &state, struct write_state); + if (req == NULL) { + return NULL; + } + + state->fd = fd; + state->buf = buf; + state->count = count; + + state->fde = tevent_add_fd(ev, state, fd, TEVENT_FD_WRITE, + write_handler, req); + if (tevent_req_nomem(state->fde, req)) { + return tevent_req_post(req, ev); + } + return req; +} + +static void write_handler(struct tevent_context *ev, struct tevent_fd *fde, + uint16_t flags, void *private_data) +{ + struct tevent_req *req = talloc_get_type_abort( + private_data, struct tevent_req); + struct write_state *state = tevent_req_data(req, struct write_state); + ssize_t ret; + + TALLOC_FREE(state->fde); + + if ((flags & TEVENT_FD_WRITE) == 0) { + tevent_req_error(req, EIO); + return; + } + + ret = write(state->fd, state->buf, state->count); + if (ret == -1) { + tevent_req_error(req, errno); + return; + } + state->nwritten = ret; + tevent_req_done(req); +} + +static ssize_t write_recv(struct tevent_req *req, int *perr) +{ + struct write_state *state = tevent_req_data(req, struct write_state); + int err; + + if (tevent_req_is_unix_error(req, &err)) { + if (perr != NULL) { + *perr = err; + } + return -1; + } + return state->nwritten; +} + +/** + * @brief Wrapper function that deals with short writes + */ + +struct writeall_state { + struct tevent_context *ev; + int fd; + const void *buf; + size_t count; + size_t nwritten; +}; + +static void writeall_done(struct tevent_req *subreq); + +static struct tevent_req *writeall_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd, const void *buf, size_t count) +{ + struct tevent_req *req, *subreq; + struct writeall_state *state; + + req = tevent_req_create(mem_ctx, &state, struct writeall_state); + if (req == NULL) { + return NULL; + } + state->ev = ev; + state->fd = fd; + state->buf = buf; + state->count = count; + state->nwritten = 0; + + subreq = write_send(state, state->ev, state->fd, + ((char *)state->buf)+state->nwritten, + state->count - state->nwritten); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, writeall_done, req); + return req; +} + +static void writeall_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct writeall_state *state = tevent_req_data( + req, struct writeall_state); + ssize_t nwritten; + int err = 0; + + nwritten = write_recv(subreq, &err); + TALLOC_FREE(subreq); + if (nwritten == -1) { + tevent_req_error(req, err); + return; + } + + state->nwritten += nwritten; + + if (state->nwritten < state->count) { + subreq = write_send(state, state->ev, state->fd, + ((char *)state->buf)+state->nwritten, + state->count - state->nwritten); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, writeall_done, req); + return; + } + tevent_req_done(req); +} + +static ssize_t writeall_recv(struct tevent_req *req, int *perr) +{ + struct writeall_state *state = tevent_req_data( + req, struct writeall_state); + int err; + + if (tevent_req_is_unix_error(req, &err)) { + if (perr != NULL) { + *perr = err; + } + return -1; + } + return state->nwritten; +} + +/** + * @brief Async echo handler code dealing with one client + */ + +struct echo_state { + struct tevent_context *ev; + int fd; + uint8_t *buf; +}; + +static int echo_state_destructor(struct echo_state *s); +static void echo_read_done(struct tevent_req *subreq); +static void echo_writeall_done(struct tevent_req *subreq); + +static struct tevent_req *echo_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int fd, size_t bufsize) +{ + struct tevent_req *req, *subreq; + struct echo_state *state; + + req = tevent_req_create(mem_ctx, &state, struct echo_state); + if (req == NULL) { + return NULL; + } + state->ev = ev; + state->fd = fd; + + talloc_set_destructor(state, echo_state_destructor); + + state->buf = talloc_array(state, uint8_t, bufsize); + if (tevent_req_nomem(state->buf, req)) { + return tevent_req_post(req, ev); + } + + subreq = read_send(state, state->ev, state->fd, + state->buf, talloc_get_size(state->buf)); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, echo_read_done, req); + return req; +} + +static int echo_state_destructor(struct echo_state *s) +{ + if (s->fd != -1) { + printf("Closing client fd %d\n", s->fd); + close(s->fd); + s->fd = -1; + } + return 0; +} + +static void echo_read_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct echo_state *state = tevent_req_data( + req, struct echo_state); + ssize_t nread; + int err; + + nread = read_recv(subreq, &err); + TALLOC_FREE(subreq); + if (nread == -1) { + tevent_req_error(req, err); + return; + } + if (nread == 0) { + tevent_req_done(req); + return; + } + + subreq = writeall_send(state, state->ev, state->fd, state->buf, nread); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, echo_writeall_done, req); +} + +static void echo_writeall_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct echo_state *state = tevent_req_data( + req, struct echo_state); + ssize_t nwritten; + int err; + + nwritten = writeall_recv(subreq, &err); + TALLOC_FREE(subreq); + if (nwritten == -1) { + if (err == EPIPE) { + tevent_req_done(req); + return; + } + tevent_req_error(req, err); + return; + } + + subreq = read_send(state, state->ev, state->fd, + state->buf, talloc_get_size(state->buf)); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, echo_read_done, req); +} + +static bool echo_recv(struct tevent_req *req, int *perr) +{ + int err; + + if (tevent_req_is_unix_error(req, &err)) { + *perr = err; + return false; + } + return true; +} + +/** + * @brief Full echo handler code accepting and handling clients + */ + +struct echo_server_state { + struct tevent_context *ev; + int listen_sock; +}; + +static void echo_server_accepted(struct tevent_req *subreq); +static void echo_server_client_done(struct tevent_req *subreq); + +static struct tevent_req *echo_server_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + int listen_sock) +{ + struct tevent_req *req, *subreq; + struct echo_server_state *state; + + req = tevent_req_create(mem_ctx, &state, + struct echo_server_state); + if (req == NULL) { + return NULL; + } + state->ev = ev; + state->listen_sock = listen_sock; + + subreq = accept_send(state, state->ev, state->listen_sock); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, echo_server_accepted, req); + return req; +} + +static void echo_server_accepted(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct echo_server_state *state = tevent_req_data( + req, struct echo_server_state); + int sock, err; + + sock = accept_recv(subreq, NULL, NULL, &err); + TALLOC_FREE(subreq); + if (sock == -1) { + tevent_req_error(req, err); + return; + } + + printf("new client fd %d\n", sock); + + subreq = echo_send(state, state->ev, sock, 100); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, echo_server_client_done, req); + + subreq = accept_send(state, state->ev, state->listen_sock); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, echo_server_accepted, req); +} + +static void echo_server_client_done(struct tevent_req *subreq) +{ + bool ret; + int err; + + ret = echo_recv(subreq, &err); + TALLOC_FREE(subreq); + + if (ret) { + printf("Client done\n"); + } else { + printf("Client failed: %s\n", strerror(err)); + } +} + +static bool echo_server_recv(struct tevent_req *req, int *perr) +{ + int err; + + if (tevent_req_is_unix_error(req, &err)) { + *perr = err; + return false; + } + return true; +} + +int main(int argc, const char **argv) +{ + int ret, port, listen_sock, err; + struct tevent_context *ev; + struct sockaddr_in addr; + struct tevent_req *req; + bool result; + + if (argc != 2) { + fprintf(stderr, "Usage: %s <port>\n", argv[0]); + exit(1); + } + + port = atoi(argv[1]); + + printf("listening on port %d\n", port); + + listen_sock = socket(AF_INET, SOCK_STREAM, 0); + + if (listen_sock == -1) { + perror("socket() failed"); + exit(1); + } + + addr = (struct sockaddr_in) { + .sin_family = AF_INET, + .sin_port = htons(port) + }; + + ret = bind(listen_sock, (struct sockaddr *)&addr, sizeof(addr)); + if (ret == -1) { + perror("bind() failed"); + exit(1); + } + + ret = listen(listen_sock, 5); + if (ret == -1) { + perror("listen() failed"); + exit(1); + } + + ev = tevent_context_init(NULL); + if (ev == NULL) { + fprintf(stderr, "tevent_context_init failed\n"); + exit(1); + } + + req = echo_server_send(ev, ev, listen_sock); + if (req == NULL) { + fprintf(stderr, "echo_server_send failed\n"); + exit(1); + } + + if (!tevent_req_poll(req, ev)) { + perror("tevent_req_poll() failed"); + exit(1); + } + + result = echo_server_recv(req, &err); + TALLOC_FREE(req); + if (!result) { + fprintf(stderr, "echo_server failed: %s\n", strerror(err)); + exit(1); + } + + return 0; +} diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c new file mode 100644 index 0000000..62dfe24 --- /dev/null +++ b/lib/tevent/pytevent.c @@ -0,0 +1,945 @@ +/* + 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 "replace.h" +#include <tevent.h> + +#if PY_MAJOR_VERSION >= 3 +#define PyLong_FromLong PyLong_FromLong +#endif + +/* discard signature of 'func' in favour of 'target_sig' */ +#define PY_DISCARD_FUNC_SIG(target_sig, func) (target_sig)(void(*)(void))func + +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; + PyObject *callback; +} TeventTimer_Object; + +typedef struct { + PyObject_HEAD + struct tevent_fd *fd; +} TeventFd_Object; + +static PyTypeObject TeventContext_Type; +static PyTypeObject TeventReq_Type; +static PyTypeObject TeventQueue_Type; +static PyTypeObject TeventSignal_Type; +static PyTypeObject TeventTimer_Type; +static 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 (!PyUnicode_Check(name)) { + PyErr_SetNone(PyExc_TypeError); + Py_DECREF(name); + return NULL; + } + + if (!tevent_register_backend(PyUnicode_AsUTF8(name), &py_tevent_ops)) { /* FIXME: What to do with backend */ + PyErr_SetNone(PyExc_RuntimeError); + Py_DECREF(name); + return NULL; + } + + Py_DECREF(name); + + Py_RETURN_NONE; +} + +static PyObject *py_tevent_context_reinitialise(TeventContext_Object *self, + PyObject *Py_UNUSED(ignored)) +{ + 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, + PyObject *Py_UNUSED(ignored)) +{ + tevent_queue_stop(self->queue); + Py_RETURN_NONE; +} + +static PyObject *py_tevent_queue_start(TeventQueue_Object *self, + PyObject *Py_UNUSED(ignored)) +{ + 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, discard_const_p(char, "")); + 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)" }, + {0}, +}; + +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, + PyObject *Py_UNUSED(ignored)) +{ + 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, + PyObject *Py_UNUSED(ignored)) +{ + if (tevent_loop_once(self->ev) != 0) { + PyErr_SetNone(PyExc_RuntimeError); + return NULL; + } + Py_RETURN_NONE; +} + +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, discard_const_p(char, "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) +{ + TeventTimer_Object *self = private_data; + PyObject *ret; + + ret = PyObject_CallFunction(self->callback, discard_const_p(char, "l"), te); + if (ret == NULL) { + /* No Python stack to propagate exception to; just print traceback */ + PyErr_PrintEx(0); + } + Py_XDECREF(ret); +} + +static void py_tevent_timer_dealloc(TeventTimer_Object *self) +{ + if (self->timer) { + talloc_free(self->timer); + } + Py_DECREF(self->callback); + PyObject_Del(self); +} + +static int py_tevent_timer_traverse(TeventTimer_Object *self, visitproc visit, void *arg) +{ + Py_VISIT(self->callback); + return 0; +} + +static PyObject* py_tevent_timer_get_active(TeventTimer_Object *self, + PyObject *Py_UNUSED(ignored)) +{ + return PyBool_FromLong(self->timer != NULL); +} + +struct PyGetSetDef py_tevent_timer_getset[] = { + { + .name = discard_const_p(char, "active"), + .get = (getter)py_tevent_timer_get_active, + .doc = discard_const_p(char, "true if the timer is scheduled to run"), + }, + {0}, +}; + +static PyTypeObject TeventTimer_Type = { + .tp_name = "tevent.Timer", + .tp_basicsize = sizeof(TeventTimer_Object), + .tp_dealloc = (destructor)py_tevent_timer_dealloc, + .tp_traverse = (traverseproc)py_tevent_timer_traverse, + .tp_getset = py_tevent_timer_getset, + .tp_flags = Py_TPFLAGS_DEFAULT, +}; + +struct TeventTimer_Object_ref { + TeventTimer_Object *obj; +}; + +static int TeventTimer_Object_ref_destructor(struct TeventTimer_Object_ref *ref) +{ + ref->obj->timer = NULL; + Py_DECREF(ref->obj); + return 0; +} + +static PyObject *py_tevent_context_add_timer_internal(TeventContext_Object *self, + struct timeval next_event, + PyObject *callback) +{ + /* Ownership notes: + * + * There are 5 pieces in play; two tevent contexts and 3 Python objects: + * - The tevent timer + * - The tevent context + * - The Python context -- "self" + * - The Python timer (TeventTimer_Object) -- "ret" + * - The Python callback function -- "callback" + * + * We only use the Python context for getting the tevent context, + * afterwards it can be destroyed. + * + * The tevent context owns the tevent timer. + * + * The tevent timer holds a reference to the Python timer, so the Python + * timer must always outlive the tevent timer. + * The Python timer has a pointer to the tevent timer; a destructor is + * used to set this to NULL when the tevent timer is deallocated. + * + * The tevent timer can be deallocated in these cases: + * 1) when the context is destroyed + * 2) after the event fires + * Posssibly, API might be added to cancel (free the tevent timer). + * + * The Python timer holds a reference to the callback. + */ + TeventTimer_Object *ret; + struct TeventTimer_Object_ref *ref; + + ret = PyObject_New(TeventTimer_Object, &TeventTimer_Type); + if (ret == NULL) { + PyErr_NoMemory(); + return NULL; + } + Py_INCREF(callback); + ret->callback = callback; + ret->timer = tevent_add_timer(self->ev, NULL, next_event, py_timer_handler, + ret); + if (ret->timer == NULL) { + Py_DECREF(ret); + PyErr_SetString(PyExc_RuntimeError, "Could not initialize timer"); + return NULL; + } + ref = talloc(ret->timer, struct TeventTimer_Object_ref); + if (ref == NULL) { + talloc_free(ret->timer); + Py_DECREF(ret); + PyErr_SetString(PyExc_RuntimeError, "Could not initialize timer"); + return NULL; + } + Py_INCREF(ret); + ref->obj = ret; + + talloc_set_destructor(ref, TeventTimer_Object_ref_destructor); + + return (PyObject *)ret; +} + +static PyObject *py_tevent_context_add_timer(TeventContext_Object *self, PyObject *args) +{ + struct timeval next_event; + PyObject *callback; + double secs, usecs; + if (!PyArg_ParseTuple(args, "dO", &secs, &callback)){ + return NULL; + } + next_event.tv_sec = secs; + usecs = (secs - next_event.tv_sec) * 1000000.0; + next_event.tv_usec = usecs; + return py_tevent_context_add_timer_internal(self, next_event, callback); +} + +static PyObject *py_tevent_context_add_timer_offset(TeventContext_Object *self, PyObject *args) +{ + struct timeval next_event; + double offset; + int seconds; + PyObject *callback; + if (!PyArg_ParseTuple(args, "dO", &offset, &callback)) + return NULL; + + seconds = offset; + offset -= seconds; + next_event = tevent_timeval_current_ofs(seconds, (int)(offset*1000000)); + return py_tevent_context_add_timer_internal(self, next_event, callback); +} + +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, discard_const_p(char, "i"), flags); + Py_XDECREF(ret); +} + +static void py_tevent_fp_dealloc(TeventFd_Object *self) +{ + talloc_free(self->fd); + PyObject_Del(self); +} + +static PyTypeObject TeventFd_Type = { + .tp_name = "tevent.Fd", + .tp_basicsize = sizeof(TeventFd_Object), + .tp_dealloc = (destructor)py_tevent_fp_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, +}; + +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; +} + +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()" }, + { "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_timer_offset", (PyCFunction)py_tevent_context_add_timer_offset, + METH_VARARGS, "S.add_timer_offset(offset_seconds, handler) -> timer" }, + { "add_fd", (PyCFunction)py_tevent_context_add_fd, + METH_VARARGS, "S.add_fd(fd, flags, handler) -> fd" }, + {0}, +}; + +static PyObject *py_tevent_req_wakeup_recv(PyObject *self, + PyObject *Py_UNUSED(ignored)) +{ + /* FIXME */ + Py_RETURN_NONE; +} + +static PyObject *py_tevent_req_received(PyObject *self, + PyObject *Py_UNUSED(ignored)) +{ + /* FIXME */ + Py_RETURN_NONE; +} + +static PyObject *py_tevent_req_is_error(PyObject *self, + PyObject *Py_UNUSED(ignored)) +{ + /* FIXME */ + Py_RETURN_NONE; +} + +static PyObject *py_tevent_req_poll(PyObject *self, + PyObject *Py_UNUSED(ignored)) +{ + /* FIXME */ + Py_RETURN_NONE; +} + +static PyObject *py_tevent_req_is_in_progress(PyObject *self, + PyObject *Py_UNUSED(ignored)) +{ + /* FIXME */ + Py_RETURN_NONE; +} + +static PyGetSetDef py_tevent_req_getsetters[] = { + { + .name = discard_const_p(char, "in_progress"), + .get = (getter)py_tevent_req_is_in_progress, + .doc = discard_const_p(char, "Whether the request is in progress"), + }, + {0} +}; + +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, + PyObject *Py_UNUSED(ignored)) +{ + /* FIXME */ + Py_RETURN_NONE; +} + +static PyObject *py_tevent_req_notify_callback(PyObject *self, + PyObject *Py_UNUSED(ignored)) +{ + /* 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, + PyObject *Py_UNUSED(ignored)) +{ + 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()" }, + {0} +}; + +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, + PyObject *Py_UNUSED(ignored)) +{ + return PyLong_FromLong(tevent_queue_length(self->queue)); +} + +static PyGetSetDef py_tevent_queue_getsetters[] = { + { + .name = discard_const_p(char, "length"), + .get = (getter)py_tevent_queue_get_length, + .doc = discard_const_p(char, "The number of elements in the queue."), + }, + {0}, +}; + +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, + PyObject *Py_UNUSED(ignored)) +{ + TeventContext_Object *self = (TeventContext_Object *)_self; + return PyBool_FromLong(tevent_signal_support(self->ev)); +} + +static PyGetSetDef py_tevent_context_getsetters[] = { + { + .name = discard_const_p(char, "signal_support"), + .get = PY_DISCARD_FUNC_SIG(getter, + py_tevent_context_signal_support), + .doc = discard_const_p(char, "if this platform and tevent context support signal handling"), + }, + {0} +}; + +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", discard_const_p(char *, 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 *Py_UNUSED(ignored)) +{ + PyObject *ret = NULL; + PyObject *string = NULL; + int i, result; + const char **backends = NULL; + + ret = PyList_New(0); + if (ret == NULL) { + return NULL; + } + + backends = tevent_backend_list(NULL); + if (backends == NULL) { + PyErr_SetNone(PyExc_RuntimeError); + goto err; + } + for (i = 0; backends[i]; i++) { + string = PyUnicode_FromString(backends[i]); + if (!string) { + goto err; + } + result = PyList_Append(ret, string); + if (result) { + goto err; + } + Py_DECREF(string); + string = NULL; + } + + talloc_free(backends); + + return ret; + +err: + Py_XDECREF(ret); + Py_XDECREF(string); + talloc_free(backends); + return NULL; +} + +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" }, + {0}, +}; + +#define MODULE_DOC PyDoc_STR("Python wrapping of talloc-maintained objects.") + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + .m_name = "_tevent", + .m_doc = MODULE_DOC, + .m_size = -1, + .m_methods = tevent_methods, +}; +#endif + +PyObject * module_init(void); +PyObject * module_init(void) +{ + PyObject *m; + + if (PyType_Ready(&TeventContext_Type) < 0) + return NULL; + + if (PyType_Ready(&TeventQueue_Type) < 0) + return NULL; + + if (PyType_Ready(&TeventReq_Type) < 0) + return NULL; + + if (PyType_Ready(&TeventSignal_Type) < 0) + return NULL; + + if (PyType_Ready(&TeventTimer_Type) < 0) + return NULL; + + if (PyType_Ready(&TeventFd_Type) < 0) + return NULL; + +#if PY_MAJOR_VERSION >= 3 + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule3("_tevent", tevent_methods, MODULE_DOC); +#endif + if (m == NULL) + return NULL; + + 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_AddStringConstant(m, "__version__", PACKAGE_VERSION); + + return m; +} + +#if PY_MAJOR_VERSION >= 3 +PyMODINIT_FUNC PyInit__tevent(void); +PyMODINIT_FUNC PyInit__tevent(void) +{ + return module_init(); +} +#else +void init_tevent(void); +void init_tevent(void) +{ + module_init(); +} +#endif diff --git a/lib/tevent/test_req.c b/lib/tevent/test_req.c new file mode 100644 index 0000000..2274a8c --- /dev/null +++ b/lib/tevent/test_req.c @@ -0,0 +1,288 @@ +/* + * Unix SMB/CIFS implementation. + * + * testing of some tevent_req aspects + * + * Copyright (C) Volker Lendecke 2018 + * + * ** 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 "includes.h" +#include "tevent.h" +#include "torture/torture.h" +#include "torture/local/proto.h" +#include "lib/util/tevent_unix.h" +#include "lib/util/tevent_req_profile.h" +#include "lib/util/time_basic.h" + +struct tevent_req_create_state { + uint8_t val; +}; + +static bool test_tevent_req_create(struct torture_context *tctx, + const void *test_data) +{ + struct tevent_req *req; + struct tevent_req_create_state *state; + + req = tevent_req_create(tctx, &state, + struct tevent_req_create_state); + torture_assert_not_null(tctx, req, "tevent_req_create failed\n"); + torture_assert_int_equal(tctx, state->val, 0, "state not initialized\n"); + + TALLOC_FREE(req); + + return true; +} + +struct profile1_state { + uint8_t dummy; +}; + +static bool test_tevent_req_profile1(struct torture_context *tctx, + const void *test_data) +{ + struct tevent_req *req; + struct profile1_state *state; + const struct tevent_req_profile *p1; + struct tevent_req_profile *p2; + struct timeval start, stop; + bool ok; + int cmp; + + req = tevent_req_create(tctx, &state, struct profile1_state); + torture_assert_not_null(tctx, req, "tevent_req_create failed\n"); + + p1 = tevent_req_get_profile(req); + torture_assert(tctx, p1 == NULL, "profile not initialized to NULL\n"); + + ok = tevent_req_set_profile(req); + torture_assert(tctx, ok, "set_profile failed\n"); + + tevent_req_done(req); + + p2 = tevent_req_move_profile(req, tctx); + torture_assert_not_null(tctx, p2, "get_profile failed\n"); + + /* Demonstrate sure "p2" outlives req */ + TALLOC_FREE(req); + + tevent_req_profile_get_start(p2, NULL, &start); + tevent_req_profile_get_stop(p2, NULL, &stop); + + cmp = tevent_timeval_compare(&start, &stop); + torture_assert(tctx, cmp <= 0, "stop before start\n"); + + TALLOC_FREE(p2); + + return true; +} + +struct profile2_state { + uint8_t dummy; +}; + +static void profile2_done(struct tevent_req *subreq); + +static struct tevent_req *profile2_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev) +{ + struct tevent_req *req, *subreq; + struct profile2_state *state; + bool ok; + + req = tevent_req_create(mem_ctx, &state, struct profile2_state); + if (req == NULL) { + return NULL; + } + + ok = tevent_req_set_profile(req); + if (!ok) { + return tevent_req_post(req, ev); + } + + subreq = tevent_wakeup_send( + state, + ev, + tevent_timeval_current_ofs(0, 1)); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, profile2_done, req); + + return req; +} + +static void profile2_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + bool ok; + + ok = tevent_wakeup_recv(subreq); + if (!ok) { + tevent_req_oom(req); + return; + } + tevent_req_done(req); +} + +static int profile2_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, + struct tevent_req_profile **profile) +{ + int err; + + if (tevent_req_is_unix_error(req, &err)) { + return err; + } + + *profile = tevent_req_move_profile(req, mem_ctx); + + return 0; +} + +static bool test_tevent_req_profile2(struct torture_context *tctx, + const void *test_data) +{ + struct tevent_context *ev; + struct tevent_req *req; + struct tevent_req_profile *p1 = NULL; + struct tevent_req_profile *p2 = NULL; + const char *str1, *str2; + struct timeval tv1, tv2; + pid_t pid1, pid2; + enum tevent_req_state state1, state2; + uint64_t err1, err2; + char *printstring; + ssize_t pack_len; + int err; + bool ok; + + ev = samba_tevent_context_init(tctx); + torture_assert_not_null(tctx, ev, "samba_tevent_context_init failed\n"); + + req = profile2_send(tctx, ev); + torture_assert_not_null(tctx, req, "profile2_send failed\n"); + + ok = tevent_req_poll_unix(req, ev, &err); + torture_assert(tctx, ok, "tevent_req_poll_unix failed\n"); + + err = profile2_recv(req, tctx, &p1); + torture_assert_int_equal(tctx, err, 0, "profile2_recv failed\n"); + + TALLOC_FREE(req); + TALLOC_FREE(ev); + + printstring = tevent_req_profile_string(tctx, p1, 0, UINT_MAX); + torture_assert_not_null( + tctx, + printstring, + "tevent_req_profile_string failed\n"); + printf("%s\n", printstring); + + pack_len = tevent_req_profile_pack(p1, NULL, 0); + torture_assert(tctx, pack_len>0, "profile_pack failed\n"); + + { + uint8_t buf[pack_len]; + ssize_t unpack_len; + + tevent_req_profile_pack(p1, buf, sizeof(buf)); + dump_data(10, buf, sizeof(buf)); + + unpack_len = tevent_req_profile_unpack( + buf, + pack_len, + tctx, + &p2); + torture_assert_int_equal(tctx, + pack_len, + unpack_len, + "profile_unpack failed\n"); + } + + printstring = tevent_req_profile_string(tctx, p2, 0, UINT_MAX); + torture_assert_not_null( + tctx, + printstring, + "tevent_req_profile_string failed\n"); + printf("%s\n", printstring); + + tevent_req_profile_get_name(p1, &str1); + tevent_req_profile_get_name(p2, &str2); + torture_assert_str_equal(tctx, str1, str2, "names differ\n"); + + tevent_req_profile_get_start(p1, &str1, &tv1); + tevent_req_profile_get_start(p2, &str2, &tv2); + torture_assert_str_equal(tctx, str1, str2, "start strings differ\n"); + torture_assert(tctx, + tevent_timeval_compare(&tv1, &tv2) == 0, + "start times differ\n"); + + tevent_req_profile_get_stop(p1, &str1, &tv1); + tevent_req_profile_get_stop(p2, &str2, &tv2); + torture_assert_str_equal(tctx, str1, str2, "stop strings differ\n"); + torture_assert(tctx, + tevent_timeval_compare(&tv1, &tv2) == 0, + "stop times differ\n"); + + tevent_req_profile_get_status(p1, &pid1, &state1, &err1); + tevent_req_profile_get_status(p2, &pid2, &state2, &err2); + torture_assert_int_equal(tctx, pid1, pid2, "pids differ\n"); + torture_assert_int_equal(tctx, state1, state2, "states differ\n"); + torture_assert_int_equal(tctx, err1, err2, "user errors differ\n"); + + str1 = tevent_req_profile_string(p1, p1, 0, UINT_MAX); + torture_assert_not_null(tctx, str1, "profile_string failed\n"); + str2 = tevent_req_profile_string(p2, p2, 0, UINT_MAX); + torture_assert_not_null(tctx, str2, "profile_string failed\n"); + + torture_assert_str_equal(tctx, str1, str2, "result strings differ\n"); + + TALLOC_FREE(p1); + TALLOC_FREE(p2); + + return true; +} + +struct torture_suite *torture_local_tevent_req(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite; + + suite = torture_suite_create(mem_ctx, "tevent_req"); + + torture_suite_add_simple_tcase_const( + suite, + "create", + test_tevent_req_create, + NULL); + torture_suite_add_simple_tcase_const( + suite, + "profile1", + test_tevent_req_profile1, + NULL); + torture_suite_add_simple_tcase_const( + suite, + "profile2", + test_tevent_req_profile2, + NULL); + + return suite; +} diff --git a/lib/tevent/tests/test_tevent_tag.c b/lib/tevent/tests/test_tevent_tag.c new file mode 100644 index 0000000..2ae0e38 --- /dev/null +++ b/lib/tevent/tests/test_tevent_tag.c @@ -0,0 +1,253 @@ +/* + * Unix SMB/CIFS implementation. + * + * testing of some tevent_req aspects + * + * Copyright (C) Pavel BÅ™ezina <pbrezina@redhat.com> 2021 + * + * ** 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 <errno.h> +#include <setjmp.h> +#include <stdlib.h> +#include <stdint.h> +#include <signal.h> + +#include <talloc.h> +#include <tevent.h> +#include <cmocka.h> + +static void queue_trigger(struct tevent_req *req, void *private_data) +{ + /* Dummy handler. Just return. */ + return; +} + +static void fd_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data) +{ + /* Dummy handler. Just return. */ + return; +} + +static void timer_handler(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval current_time, + void *private_data) +{ + /* Dummy handler. Just return. */ + return; +} + +static void signal_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + /* Dummy handler. Just return. */ + return; +} + +static void immediate_handler(struct tevent_context *ctx, + struct tevent_immediate *im, + void *private_data) +{ + /* Dummy handler. Just return. */ + return; +} + +static int test_setup(void **state) +{ + struct tevent_context *ev; + + ev = tevent_context_init(NULL); + assert_non_null(ev); + + *state = ev; + return 0; +} + +static int test_teardown(void **state) +{ + struct tevent_context *ev = (struct tevent_context *)(*state); + talloc_free(ev); + return 0; +} + +static void test_fd_tag(void **state) +{ + struct tevent_context *ev = (struct tevent_context *)(*state); + struct tevent_fd *fde; + uint64_t tag; + + fde = tevent_add_fd(ev, ev, 0, TEVENT_FD_READ, fd_handler, NULL); + assert_non_null(fde); + + tag = tevent_fd_get_tag(fde); + assert_int_equal(0, tag); + + tevent_fd_set_tag(fde, 1); + tag = tevent_fd_get_tag(fde); + assert_int_equal(1, tag); + + tevent_re_initialise(ev); + + tag = tevent_fd_get_tag(fde); + assert_int_equal(1, tag); + + TALLOC_FREE(fde); +} + +static void test_timer_tag(void **state) +{ + struct tevent_context *ev = (struct tevent_context *)(*state); + struct tevent_timer *te; + struct timeval next; + uint64_t tag; + + next = tevent_timeval_current(); + te = tevent_add_timer(ev, ev, next, timer_handler, NULL); + assert_non_null(te); + + tag = tevent_timer_get_tag(te); + assert_int_equal(0, tag); + + tevent_timer_set_tag(te, 1); + tag = tevent_timer_get_tag(te); + assert_int_equal(1, tag); + + next = tevent_timeval_current(); + tevent_update_timer(te, next); + + tag = tevent_timer_get_tag(te); + assert_int_equal(1, tag); + + tevent_re_initialise(ev); + + tag = tevent_timer_get_tag(te); + assert_int_equal(1, tag); + + TALLOC_FREE(te); +} + +static void test_signal_tag(void **state) +{ + struct tevent_context *ev = (struct tevent_context *)(*state); + struct tevent_signal *se; + uint64_t tag; + + se = tevent_add_signal(ev, ev, SIGUSR1, 0, signal_handler, NULL); + assert_non_null(se); + + tag = tevent_signal_get_tag(se); + assert_int_equal(0, tag); + + tevent_signal_set_tag(se, 1); + tag = tevent_signal_get_tag(se); + assert_int_equal(1, tag); + + tevent_re_initialise(ev); + + tag = tevent_signal_get_tag(se); + assert_int_equal(1, tag); + + TALLOC_FREE(se); +} + +static void test_immediate_tag(void **state) +{ + struct tevent_context *ev = (struct tevent_context *)(*state); + struct tevent_immediate *im; + uint64_t tag; + + im = tevent_create_immediate(ev); + assert_non_null(im); + + tag = tevent_immediate_get_tag(im); + assert_int_equal(0, tag); + + tevent_immediate_set_tag(im, 1); + tag = tevent_immediate_get_tag(im); + assert_int_equal(1, tag); + + tevent_schedule_immediate(im, ev, immediate_handler, NULL); + + tag = tevent_immediate_get_tag(im); + assert_int_equal(1, tag); + + tevent_re_initialise(ev); + + tag = tevent_immediate_get_tag(im); + assert_int_equal(1, tag); + + TALLOC_FREE(im); +} + +static void test_queue_entry_tag(void **state) +{ + struct tevent_context *ev = (struct tevent_context *)(*state); + struct tevent_queue *q; + struct tevent_queue_entry *e1, *e2; + struct tevent_req *r1, *r2; + int *s1, *s2; + uint64_t tag; + + q = tevent_queue_create(ev, "test_queue"); + assert_non_null(q); + + r1 = tevent_req_create(ev, &s1, int); + r2 = tevent_req_create(ev, &s2, int); + e1 = tevent_queue_add_entry(q, ev, r1, queue_trigger, NULL); + e2 = tevent_queue_add_entry(q, ev, r2, queue_trigger, NULL); + + tag = tevent_queue_entry_get_tag(e1); + assert_int_equal(0, tag); + tag = tevent_queue_entry_get_tag(e2); + assert_int_equal(0, tag); + + tevent_queue_entry_set_tag(e1, 1); + tevent_queue_entry_set_tag(e2, 2); + + tag = tevent_queue_entry_get_tag(e1); + assert_int_equal(1, tag); + + tag = tevent_queue_entry_get_tag(e2); + assert_int_equal(2, tag); + + TALLOC_FREE(q); +} + +int main(int argc, char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(test_fd_tag, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_timer_tag, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_signal_tag, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_immediate_tag, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_queue_entry_tag, test_setup, test_teardown), + }; + + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/lib/tevent/tests/test_tevent_trace.c b/lib/tevent/tests/test_tevent_trace.c new file mode 100644 index 0000000..10e1ee0 --- /dev/null +++ b/lib/tevent/tests/test_tevent_trace.c @@ -0,0 +1,1324 @@ +/* + * Unix SMB/CIFS implementation. + * + * testing of some tevent_req aspects + * + * Copyright (C) Pavel BÅ™ezina <pbrezina@redhat.com> 2021 + * + * ** 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 <errno.h> +#include <setjmp.h> +#include <stdlib.h> +#include <stdint.h> +#include <signal.h> +#include <unistd.h> + +#include <talloc.h> +#include <tevent.h> +#include <cmocka.h> + +struct test_ctx { + struct tevent_context *ev; + + bool handler_skipped; + bool reattach_reset; + + uint64_t (*get_tag)(const void *event); + void (*set_tag)(void *event, uint64_t tag); + uint64_t current_tag; + + bool attach; + bool before_handler; + bool handler_called; + bool detach; +}; + +static void fd_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data) +{ + struct test_ctx *tctx = (struct test_ctx *)private_data; + uint64_t tag = tevent_fd_get_tag(fde); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + tctx->handler_called = true; + assert_int_equal(tag, tctx->current_tag); + return; +} + +static void timer_handler(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval current_time, + void *private_data) +{ + struct test_ctx *tctx = (struct test_ctx *)private_data; + uint64_t tag = tevent_timer_get_tag(te); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + tctx->handler_called = true; + assert_int_equal(tag, tctx->current_tag); + return; +} + +static void signal_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + struct test_ctx *tctx = (struct test_ctx *)private_data; + uint64_t tag = tevent_signal_get_tag(se); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + tctx->handler_called = true; + assert_int_equal(tag, tctx->current_tag); + return; +} + +static void immediate_handler(struct tevent_context *ctx, + struct tevent_immediate *im, + void *private_data) +{ + struct test_ctx *tctx = (struct test_ctx *)private_data; + uint64_t tag = tevent_immediate_get_tag(im); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + tctx->handler_called = true; + assert_int_equal(tag, tctx->current_tag); + return; +} + +static void immediate_handler_reschedule(struct tevent_context *ctx, + struct tevent_immediate *im, + void *private_data) +{ + struct test_ctx *tctx = (struct test_ctx *)private_data; + uint64_t tag = tevent_immediate_get_tag(im); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + tctx->handler_called = true; + assert_int_equal(tag, tctx->current_tag); + + assert_false(tctx->reattach_reset); + tctx->reattach_reset = true; + tevent_schedule_immediate(im, tctx->ev, immediate_handler, tctx); + assert_false(tctx->reattach_reset); + assert_false(tctx->handler_skipped); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + assert_int_not_equal(tag, tctx->current_tag); + tag = tevent_immediate_get_tag(im); + assert_int_equal(tag, tctx->current_tag); + + tctx->handler_skipped = true; + tctx->reattach_reset = true; + tevent_schedule_immediate(im, tctx->ev, immediate_handler, tctx); + assert_false(tctx->reattach_reset); + assert_false(tctx->handler_skipped); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + assert_int_not_equal(tag, tctx->current_tag); + tag = tevent_immediate_get_tag(im); + assert_int_equal(tag, tctx->current_tag); +} + +static void fd_handler_free(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data) +{ + struct test_ctx *tctx = (struct test_ctx *)private_data; + uint64_t tag = tevent_fd_get_tag(fde); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + tctx->handler_called = true; + assert_int_equal(tag, tctx->current_tag); + TALLOC_FREE(fde); + assert_true(tctx->detach); + return; +} + +static void timer_handler_free(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval current_time, + void *private_data) +{ + struct test_ctx *tctx = (struct test_ctx *)private_data; + uint64_t tag = tevent_timer_get_tag(te); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + tctx->handler_called = true; + assert_int_equal(tag, tctx->current_tag); + TALLOC_FREE(te); + assert_true(tctx->detach); + return; +} + +static void signal_handler_free(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + struct test_ctx *tctx = (struct test_ctx *)private_data; + uint64_t tag = tevent_signal_get_tag(se); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + tctx->handler_called = true; + assert_int_equal(tag, tctx->current_tag); + TALLOC_FREE(se); + assert_true(tctx->detach); + return; +} + +static void immediate_handler_free(struct tevent_context *ctx, + struct tevent_immediate *im, + void *private_data) +{ + struct test_ctx *tctx = (struct test_ctx *)private_data; + uint64_t tag = tevent_immediate_get_tag(im); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + tctx->handler_called = true; + assert_int_equal(tag, tctx->current_tag); + TALLOC_FREE(im); + assert_true(tctx->detach); + return; +} + +static void trace_event_cb(void *event, + enum tevent_event_trace_point point, + void *private_data) +{ + struct test_ctx *tctx = (struct test_ctx *)private_data; + uint64_t tag = tctx->get_tag(event); + + switch (point) { + case TEVENT_EVENT_TRACE_ATTACH: + if (tctx->reattach_reset) { + assert_true(tctx->attach); + assert_true(tctx->detach); + tctx->attach = false; + tctx->before_handler = false; + tctx->handler_called = false; + tctx->detach = false; + tctx->handler_skipped = false; + tctx->reattach_reset = false; + } + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + tctx->attach = true; + assert_int_equal(tag, tctx->current_tag); + tag = ++tctx->current_tag; + tctx->set_tag(event, tag); + break; + case TEVENT_EVENT_TRACE_BEFORE_HANDLER: + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + tctx->before_handler = true; + assert_int_equal(tag, tctx->current_tag); + break; + case TEVENT_EVENT_TRACE_DETACH: + assert_true(tctx->attach); + if (tctx->handler_skipped) { + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + } else { + assert_true(tctx->before_handler); + assert_true(tctx->handler_called); + } + assert_false(tctx->detach); + tctx->detach = true; + assert_int_equal(tag, tctx->current_tag); + break; + } +} + +static void trace_event_cb1(void *event, + enum tevent_event_trace_point point, + void *private_data) +{ + struct test_ctx *tctx = (struct test_ctx *)private_data; + uint64_t tag; + + switch (point) { + case TEVENT_EVENT_TRACE_ATTACH: + tctx->attach = true; + tag = ++tctx->current_tag; + tctx->set_tag(event, tag); + break; + case TEVENT_EVENT_TRACE_BEFORE_HANDLER: + tctx->before_handler = true; + break; + case TEVENT_EVENT_TRACE_DETACH: + tctx->detach = true; + break; + } +} + +static int test_setup(void **state) +{ + struct test_ctx *tctx; + + tctx = talloc_zero(NULL, struct test_ctx); + assert_non_null(tctx); + + tctx->ev = tevent_context_init(tctx); + assert_non_null(tctx->ev); + + *state = tctx; + return 0; +} + +static int test_teardown(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + tctx->get_tag = NULL; + tctx->set_tag = NULL; + tevent_set_trace_fd_callback(tctx->ev, NULL, NULL); + tevent_set_trace_timer_callback(tctx->ev, NULL, NULL); + tevent_set_trace_signal_callback(tctx->ev, NULL, NULL); + tevent_set_trace_immediate_callback(tctx->ev, NULL, NULL); + TALLOC_FREE(tctx); + return 0; +} + +static uint64_t fd_get_tag(const void *_event) +{ + const struct tevent_fd *event = + (const struct tevent_fd *)_event; + + return tevent_fd_get_tag(event); +} + +static void fd_set_tag(void *_event, uint64_t tag) +{ + struct tevent_fd *event = + (struct tevent_fd *)_event; + + tevent_fd_set_tag(event, tag); +} + +static uint64_t timer_get_tag(const void *_event) +{ + const struct tevent_timer *event = + (const struct tevent_timer *)_event; + + return tevent_timer_get_tag(event); +} + +static void timer_set_tag(void *_event, uint64_t tag) +{ + struct tevent_timer *event = + (struct tevent_timer *)_event; + + tevent_timer_set_tag(event, tag); +} + +static uint64_t signal_get_tag(const void *_event) +{ + const struct tevent_signal *event = + (const struct tevent_signal *)_event; + + return tevent_signal_get_tag(event); +} + +static void signal_set_tag(void *_event, uint64_t tag) +{ + struct tevent_signal *event = + (struct tevent_signal *)_event; + + tevent_signal_set_tag(event, tag); +} + +static uint64_t immediate_get_tag(const void *_event) +{ + const struct tevent_immediate *event = + (const struct tevent_immediate *)_event; + + return tevent_immediate_get_tag(event); +} + +static void immediate_set_tag(void *_event, uint64_t tag) +{ + struct tevent_immediate *event = + (struct tevent_immediate *)_event; + + tevent_immediate_set_tag(event, tag); +} + +static uint64_t queue_entry_get_tag(const void *_event) +{ + const struct tevent_queue_entry *event = + (const struct tevent_queue_entry *)_event; + + return tevent_queue_entry_get_tag(event); +} + +static void queue_entry_set_tag(void *_event, uint64_t tag) +{ + struct tevent_queue_entry *event = + (struct tevent_queue_entry *)_event; + + tevent_queue_entry_set_tag(event, tag); +} + +static void test_trace_event_fd__loop(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_fd *fde; + + tctx->get_tag = fd_get_tag; + tctx->set_tag = fd_set_tag; + tevent_set_trace_fd_callback(tctx->ev, (tevent_trace_fd_callback_t)trace_event_cb, tctx); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + fde = tevent_add_fd(tctx->ev, tctx, 0, TEVENT_FD_WRITE, fd_handler, tctx); + assert_non_null(fde); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + TEVENT_FD_WRITEABLE(fde); + tevent_loop_once(tctx->ev); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_true(tctx->handler_called); + assert_false(tctx->detach); + + TALLOC_FREE(fde); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_true(tctx->handler_called); + assert_true(tctx->detach); +} + +static void test_trace_event_fd__reset(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_fd *fde; + + tctx->get_tag = fd_get_tag; + tctx->set_tag = fd_set_tag; + tevent_set_trace_fd_callback(tctx->ev, (tevent_trace_fd_callback_t)trace_event_cb, tctx); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + fde = tevent_add_fd(tctx->ev, tctx, 0, TEVENT_FD_WRITE, fd_handler, tctx); + assert_non_null(fde); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + tctx->handler_skipped = true; + tevent_re_initialise(tctx->ev); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_true(tctx->detach); +} + +static void test_trace_event_fd__free(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_fd *fde; + + tctx->get_tag = fd_get_tag; + tctx->set_tag = fd_set_tag; + tevent_set_trace_fd_callback(tctx->ev, (tevent_trace_fd_callback_t)trace_event_cb, tctx); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + fde = tevent_add_fd(tctx->ev, tctx, 0, TEVENT_FD_WRITE, fd_handler, tctx); + assert_non_null(fde); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + tctx->handler_skipped = true; + TALLOC_FREE(fde); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_true(tctx->detach); +} + +static void test_trace_event_fd__free_in_handler(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_fd *fde; + + tctx->get_tag = fd_get_tag; + tctx->set_tag = fd_set_tag; + tevent_set_trace_fd_callback(tctx->ev, (tevent_trace_fd_callback_t)trace_event_cb, tctx); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + fde = tevent_add_fd(tctx->ev, tctx, 0, TEVENT_FD_WRITE, fd_handler_free, tctx); + assert_non_null(fde); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + TEVENT_FD_WRITEABLE(fde); + tevent_loop_once(tctx->ev); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_true(tctx->handler_called); + assert_true(tctx->detach); +} + +static void test_trace_event_timer__loop(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_timer *te; + struct timeval next; + + tctx->get_tag = timer_get_tag; + tctx->set_tag = timer_set_tag; + tevent_set_trace_timer_callback(tctx->ev, (tevent_trace_timer_callback_t)trace_event_cb, tctx); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + next = tevent_timeval_current(); + te = tevent_add_timer(tctx->ev, tctx, next, timer_handler, tctx); + assert_non_null(te); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + tevent_loop_once(tctx->ev); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_true(tctx->handler_called); + /* timer events are self destructing after calling the handler */ + assert_true(tctx->detach); +} + +static void test_trace_event_timer__reset(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_timer *te; + struct timeval next; + + tctx->get_tag = timer_get_tag; + tctx->set_tag = timer_set_tag; + tevent_set_trace_timer_callback(tctx->ev, (tevent_trace_timer_callback_t)trace_event_cb, tctx); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + next = tevent_timeval_current(); + te = tevent_add_timer(tctx->ev, tctx, next, timer_handler, tctx); + assert_non_null(te); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + assert_true(tctx->attach); + + assert_false(tctx->reattach_reset); + tctx->handler_skipped = true; + tctx->reattach_reset = true; + next = tevent_timeval_current(); + tevent_update_timer(te, next); + assert_false(tctx->reattach_reset); + assert_false(tctx->handler_skipped); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + tctx->handler_skipped = true; + tevent_re_initialise(tctx->ev); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_true(tctx->detach); +} + +static void test_trace_event_timer__free(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_timer *te; + struct timeval next; + + tctx->get_tag = timer_get_tag; + tctx->set_tag = timer_set_tag; + tevent_set_trace_timer_callback(tctx->ev, (tevent_trace_timer_callback_t)trace_event_cb, tctx); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + next = tevent_timeval_current(); + te = tevent_add_timer(tctx->ev, tctx, next, timer_handler, tctx); + assert_non_null(te); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + assert_true(tctx->attach); + + tctx->handler_skipped = true; + TALLOC_FREE(te); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_true(tctx->detach); +} + +static void test_trace_event_timer__free_in_handler(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_timer *te; + struct timeval next; + + tctx->get_tag = timer_get_tag; + tctx->set_tag = timer_set_tag; + tevent_set_trace_timer_callback(tctx->ev, (tevent_trace_timer_callback_t)trace_event_cb, tctx); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + next = tevent_timeval_current(); + te = tevent_add_timer(tctx->ev, tctx, next, timer_handler_free, tctx); + assert_non_null(te); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + tevent_loop_once(tctx->ev); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_true(tctx->handler_called); + assert_true(tctx->detach); +} + +static void test_trace_event_signal__loop(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_signal *se; + + tctx->get_tag = signal_get_tag; + tctx->set_tag = signal_set_tag; + tevent_set_trace_signal_callback(tctx->ev, (tevent_trace_signal_callback_t)trace_event_cb, tctx); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + se = tevent_add_signal(tctx->ev, tctx, SIGUSR1, 0, signal_handler, tctx); + assert_non_null(se); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + kill(getpid(), SIGUSR1); + tevent_loop_once(tctx->ev); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_true(tctx->handler_called); + assert_false(tctx->detach); + + TALLOC_FREE(se); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_true(tctx->handler_called); + assert_true(tctx->detach); +} + +static void test_trace_event_signal__reset(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_signal *se; + + tctx->get_tag = signal_get_tag; + tctx->set_tag = signal_set_tag; + tevent_set_trace_signal_callback(tctx->ev, (tevent_trace_signal_callback_t)trace_event_cb, tctx); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + se = tevent_add_signal(tctx->ev, tctx, SIGUSR1, 0, signal_handler, tctx); + assert_non_null(se); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + tctx->handler_skipped = true; + TALLOC_FREE(se); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_true(tctx->detach); +} + +static void test_trace_event_signal__free(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_signal *se; + + tctx->get_tag = signal_get_tag; + tctx->set_tag = signal_set_tag; + tevent_set_trace_signal_callback(tctx->ev, (tevent_trace_signal_callback_t)trace_event_cb, tctx); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + se = tevent_add_signal(tctx->ev, tctx, SIGUSR1, 0, signal_handler, tctx); + assert_non_null(se); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + tctx->handler_skipped = true; + TALLOC_FREE(se); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_true(tctx->detach); +} + +static void test_trace_event_signal__free_in_handler(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_signal *se; + + tctx->get_tag = signal_get_tag; + tctx->set_tag = signal_set_tag; + tevent_set_trace_signal_callback(tctx->ev, (tevent_trace_signal_callback_t)trace_event_cb, tctx); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + se = tevent_add_signal(tctx->ev, tctx, SIGUSR1, 0, signal_handler_free, tctx); + assert_non_null(se); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + kill(getpid(), SIGUSR1); + tevent_loop_once(tctx->ev); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_true(tctx->handler_called); + assert_true(tctx->detach); +} + +static void test_trace_event_immediate__loop(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_immediate *im; + + tctx->get_tag = immediate_get_tag; + tctx->set_tag = immediate_set_tag; + tevent_set_trace_immediate_callback(tctx->ev, (tevent_trace_immediate_callback_t)trace_event_cb, tctx); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + im = tevent_create_immediate(tctx); + assert_non_null(im); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + tevent_schedule_immediate(im, tctx->ev, immediate_handler, tctx); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + tevent_loop_once(tctx->ev); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_true(tctx->handler_called); + /* immediate events are self detaching */ + assert_true(tctx->detach); +} + +static void test_trace_event_immediate__reset(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_immediate *im; + + tctx->get_tag = immediate_get_tag; + tctx->set_tag = immediate_set_tag; + tevent_set_trace_immediate_callback(tctx->ev, (tevent_trace_immediate_callback_t)trace_event_cb, tctx); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + im = tevent_create_immediate(tctx); + assert_non_null(im); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + tevent_schedule_immediate(im, tctx->ev, immediate_handler, tctx); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + tctx->handler_skipped = true; + tevent_re_initialise(tctx->ev); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_true(tctx->detach); +} + +static void test_trace_event_immediate__free(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_immediate *im; + + tctx->get_tag = immediate_get_tag; + tctx->set_tag = immediate_set_tag; + tevent_set_trace_immediate_callback(tctx->ev, (tevent_trace_immediate_callback_t)trace_event_cb, tctx); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + im = tevent_create_immediate(tctx); + assert_non_null(im); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + tevent_schedule_immediate(im, tctx->ev, immediate_handler, tctx); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + tctx->handler_skipped = true; + TALLOC_FREE(im); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_true(tctx->detach); +} + +static void test_trace_event_immediate__free_in_handler(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_immediate *im; + + tctx->get_tag = immediate_get_tag; + tctx->set_tag = immediate_set_tag; + tevent_set_trace_immediate_callback(tctx->ev, (tevent_trace_immediate_callback_t)trace_event_cb, tctx); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + im = tevent_create_immediate(tctx); + assert_non_null(im); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + tevent_schedule_immediate(im, tctx->ev, immediate_handler_free, tctx); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + tevent_loop_once(tctx->ev); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_true(tctx->handler_called); + assert_true(tctx->detach); +} + +static void test_trace_event_immediate__reschedule(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_immediate *im; + + tctx->get_tag = immediate_get_tag; + tctx->set_tag = immediate_set_tag; + tevent_set_trace_immediate_callback(tctx->ev, (tevent_trace_immediate_callback_t)trace_event_cb, tctx); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + im = tevent_create_immediate(tctx); + assert_non_null(im); + + assert_false(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + tevent_schedule_immediate(im, tctx->ev, immediate_handler, tctx); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + assert_false(tctx->reattach_reset); + tctx->handler_skipped = true; + tctx->reattach_reset = true; + tevent_schedule_immediate(im, tctx->ev, immediate_handler_reschedule, tctx); + assert_false(tctx->reattach_reset); + assert_false(tctx->handler_skipped); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + tevent_loop_once(tctx->ev); + assert_false(tctx->reattach_reset); + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + + tevent_loop_once(tctx->ev); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_true(tctx->handler_called); + /* immediate events are self detaching */ + assert_true(tctx->detach); +} + +struct dummy_request_state +{ + int i; + struct tevent_queue_entry *e; +}; + +static void queue_trigger(struct tevent_req *req, void *private_data) +{ + struct test_ctx *tctx = (struct test_ctx *)private_data; + struct dummy_request_state *state = tevent_req_data( + req, struct dummy_request_state); + + tctx->handler_called = true; + assert_int_equal(tevent_queue_entry_get_tag(state->e), state->i); + TALLOC_FREE(req); + + return; +} + +static void test_trace_queue__loop(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_queue *qa, *qb; + struct tevent_req *r1, *r2, *r3, *r4, *r5; + struct dummy_request_state *ds1, *ds2, *ds3, *ds4, *ds5; + + tevent_set_trace_queue_callback( + tctx->ev, + (tevent_trace_queue_callback_t)trace_event_cb1, + tctx); + tctx->get_tag = queue_entry_get_tag; + tctx->set_tag = queue_entry_set_tag; + + qa = tevent_queue_create(tctx->ev, "test_queue A"); + assert_non_null(qa); + qb = tevent_queue_create(tctx->ev, "test_queue B"); + assert_non_null(qb); + + r1 = tevent_req_create(tctx->ev, &ds1, struct dummy_request_state); + ds1->e = tevent_queue_add_entry(qa, + tctx->ev, + r1, + queue_trigger, + *state); + ds1->i = tctx->current_tag; + assert_int_equal(ds1->i, 1); + + r2 = tevent_req_create(tctx->ev, &ds2, struct dummy_request_state); + ds2->e = tevent_queue_add_entry(qa, + tctx->ev, + r2, + queue_trigger, + *state); + ds2->i = tctx->current_tag; + assert_int_equal(ds2->i, 2); + + r3 = tevent_req_create(tctx->ev, &ds3, struct dummy_request_state); + ds3->e = tevent_queue_add_entry(qb, + tctx->ev, + r3, + queue_trigger, + *state); + ds3->i = tctx->current_tag; + assert_int_equal(ds3->i, 3); + + r4 = tevent_req_create(tctx->ev, &ds4, struct dummy_request_state); + ds4->e = tevent_queue_add_entry(qb, + tctx->ev, + r4, + queue_trigger, + *state); + ds4->i = tctx->current_tag; + assert_int_equal(ds4->i, 4); + + r5 = tevent_req_create(tctx->ev, &ds5, struct dummy_request_state); + ds5->e = tevent_queue_add_entry(qa, + tctx->ev, + r5, + queue_trigger, + *state); + ds5->i = tctx->current_tag; + assert_int_equal(ds5->i, 5); + + tevent_loop_once(tctx->ev); + tevent_loop_once(tctx->ev); + tevent_loop_once(tctx->ev); + tevent_loop_once(tctx->ev); + tevent_loop_once(tctx->ev); +} + +static void reset_tctx(struct test_ctx *tctx) +{ + tctx->attach = false; + tctx->before_handler = false; + tctx->handler_called = false; + tctx->detach = false; +} + +static void test_trace_queue__extra(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + struct tevent_queue *qa; + struct tevent_req *r1, *r2, *r3; + struct dummy_request_state *ds1, *ds2, *ds3; + + tevent_set_trace_queue_callback( + tctx->ev, + (tevent_trace_queue_callback_t)trace_event_cb1, + tctx); + tctx->get_tag = queue_entry_get_tag; + tctx->set_tag = queue_entry_set_tag; + + qa = tevent_queue_create(tctx->ev, "test_queue A"); + assert_non_null(qa); + + /* + * r1 - this tests optimize_empty - request is triggered immediately, + * (and not even scheduled to tevent_context). The TALLOC_FREE() called + * from queue_trigger removes the request/queue_entry from the queue qa. + * So qa is empty + */ + r1 = tevent_req_create(tctx->ev, &ds1, struct dummy_request_state); + ds1->e = tevent_queue_add_optimize_empty(qa, + tctx->ev, + r1, + queue_trigger, + *state); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_true(tctx->handler_called); + assert_true(tctx->detach); + assert_int_equal(tevent_queue_length(qa), 0); + + reset_tctx(tctx); + + /* + * Test a blocker request r2 - the trigger function is NULL. + */ + r2 = tevent_req_create(tctx->ev, &ds2, struct dummy_request_state); + ds2->e = tevent_queue_add_entry(qa, tctx->ev, r2, NULL, *state); + ds2->i = tctx->current_tag; + assert_true(tctx->attach); + assert_false(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + assert_int_equal(tevent_queue_length(qa), 1); + + /* + * This runs the tevent_queue_noop_trigger(). + * A blocker r2 is still on the queue head, with triggered==true + */ + tevent_loop_once(tctx->ev); + + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_false(tctx->handler_called); + /* tevent_queue_noop_trigger() is a noop. Does not set handler_called */ + assert_false(tctx->detach); + assert_int_equal(tevent_queue_length(qa), 1); + + /* + * Add a normal request r3. It will be blocked by r2. + */ + r3 = tevent_req_create(tctx->ev, &ds3, struct dummy_request_state); + ds3->e = tevent_queue_add_entry(qa, + tctx->ev, + r3, + queue_trigger, + *state); + ds3->i = tctx->current_tag; + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_false(tctx->handler_called); + assert_false(tctx->detach); + assert_int_equal(tevent_queue_length(qa), 2); + + /* + * Remove the blocker r2. + */ + TALLOC_FREE(r2); + assert_true(tctx->attach); + assert_true(tctx->before_handler); + assert_false(tctx->handler_called); + assert_true(tctx->detach); + assert_int_equal(tevent_queue_length(qa), 1); + + reset_tctx(tctx); + + /* Process r3 */ + tevent_loop_once(tctx->ev); + + assert_false(tctx->attach); + assert_true(tctx->before_handler); + assert_true(tctx->handler_called); + assert_true(tctx->detach); +} + +static void test_get_set_trace_fd_callback(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + tevent_trace_fd_callback_t cb; + void *pvt; + + tevent_get_trace_fd_callback(tctx->ev, &cb, &pvt); + assert_null(cb); + assert_null(pvt); + + tevent_set_trace_fd_callback(tctx->ev, (tevent_trace_fd_callback_t)trace_event_cb, tctx); + tevent_get_trace_fd_callback(tctx->ev, &cb, &pvt); + assert_ptr_equal(cb, trace_event_cb); + assert_ptr_equal(pvt, tctx); + + tevent_set_trace_fd_callback(tctx->ev, NULL, NULL); + tevent_get_trace_fd_callback(tctx->ev, &cb, &pvt); + assert_null(cb); + assert_null(pvt); +} + +static void test_get_set_trace_timer_callback(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + tevent_trace_timer_callback_t cb; + void *pvt; + + tevent_get_trace_timer_callback(tctx->ev, &cb, &pvt); + assert_null(cb); + assert_null(pvt); + + tevent_set_trace_timer_callback(tctx->ev, (tevent_trace_timer_callback_t)trace_event_cb, tctx); + tevent_get_trace_timer_callback(tctx->ev, &cb, &pvt); + assert_ptr_equal(cb, trace_event_cb); + assert_ptr_equal(pvt, tctx); + + tevent_set_trace_timer_callback(tctx->ev, NULL, NULL); + tevent_get_trace_timer_callback(tctx->ev, &cb, &pvt); + assert_null(cb); + assert_null(pvt); +} + +static void test_get_set_trace_signal_callback(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + tevent_trace_signal_callback_t cb; + void *pvt; + + tevent_get_trace_signal_callback(tctx->ev, &cb, &pvt); + assert_null(cb); + assert_null(pvt); + + tevent_set_trace_signal_callback(tctx->ev, (tevent_trace_signal_callback_t)trace_event_cb, tctx); + tevent_get_trace_signal_callback(tctx->ev, &cb, &pvt); + assert_ptr_equal(cb, trace_event_cb); + assert_ptr_equal(pvt, tctx); + + tevent_set_trace_signal_callback(tctx->ev, NULL, NULL); + tevent_get_trace_signal_callback(tctx->ev, &cb, &pvt); + assert_null(cb); + assert_null(pvt); +} + +static void test_get_set_trace_immediate_callback(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + tevent_trace_immediate_callback_t cb; + void *pvt; + + tevent_get_trace_immediate_callback(tctx->ev, &cb, &pvt); + assert_null(cb); + assert_null(pvt); + + tevent_set_trace_immediate_callback(tctx->ev, (tevent_trace_immediate_callback_t)trace_event_cb, tctx); + tevent_get_trace_immediate_callback(tctx->ev, &cb, &pvt); + assert_ptr_equal(cb, trace_event_cb); + assert_ptr_equal(pvt, tctx); + + tevent_set_trace_immediate_callback(tctx->ev, NULL, NULL); + tevent_get_trace_immediate_callback(tctx->ev, &cb, &pvt); + assert_null(cb); + assert_null(pvt); +} + +static void test_get_set_trace_queue_callback(void **state) +{ + struct test_ctx *tctx = (struct test_ctx *)(*state); + tevent_trace_queue_callback_t cb; + void *pvt; + + tevent_get_trace_queue_callback(tctx->ev, &cb, &pvt); + assert_null(cb); + assert_null(pvt); + + tevent_set_trace_queue_callback(tctx->ev, (tevent_trace_queue_callback_t)trace_event_cb, tctx); + tevent_get_trace_queue_callback(tctx->ev, &cb, &pvt); + assert_ptr_equal(cb, trace_event_cb); + assert_ptr_equal(pvt, tctx); + + tevent_set_trace_queue_callback(tctx->ev, NULL, NULL); + tevent_get_trace_queue_callback(tctx->ev, &cb, &pvt); + assert_null(cb); + assert_null(pvt); +} + +int main(int argc, char **argv) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(test_trace_event_fd__loop, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_event_fd__reset, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_event_fd__free, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_event_fd__free_in_handler, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_event_timer__loop, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_event_timer__reset, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_event_timer__free, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_event_timer__free_in_handler, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_event_signal__loop, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_event_signal__reset, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_event_signal__free, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_event_signal__free_in_handler, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_event_immediate__loop, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_event_immediate__reset, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_event_immediate__free, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_event_immediate__free_in_handler, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_event_immediate__reschedule, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_queue__loop, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_trace_queue__extra, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_get_set_trace_fd_callback, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_get_set_trace_timer_callback, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_get_set_trace_signal_callback, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_get_set_trace_immediate_callback, test_setup, test_teardown), + cmocka_unit_test_setup_teardown(test_get_set_trace_queue_callback, test_setup, test_teardown), + }; + + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/lib/tevent/testsuite.c b/lib/tevent/testsuite.c new file mode 100644 index 0000000..8894e44 --- /dev/null +++ b/lib/tevent/testsuite.c @@ -0,0 +1,1892 @@ +/* + 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 + ** 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 "includes.h" +#define TEVENT_DEPRECATED 1 +#include "tevent.h" +#include "system/filesys.h" +#include "system/select.h" +#include "system/network.h" +#include "torture/torture.h" +#include "torture/local/proto.h" +#ifdef HAVE_PTHREAD +#include "system/threads.h" +#include <assert.h> +#endif + +static int fde_count; + +static void do_read(int fd, void *buf, size_t count) +{ + ssize_t ret; + + do { + ret = read(fd, buf, count); + } while (ret == -1 && errno == EINTR); +} + +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; + char c; +#ifdef SA_SIGINFO + kill(getpid(), SIGUSR1); +#endif + kill(getpid(), SIGALRM); + + do_read(fd[0], &c, 1); + fde_count++; +} + +static void do_write(int fd, void *buf, size_t count) +{ + ssize_t ret; + + do { + ret = write(fd, buf, count); + } while (ret == -1 && errno == EINTR); +} + +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; + + do_write(fd[1], &c, 1); +} + + +/* This will only fire if the fd's returned from pipe() are bi-directional. */ +static void fde_handler_read_1(struct tevent_context *ev_ctx, struct tevent_fd *f, + uint16_t flags, void *private_data) +{ + int *fd = (int *)private_data; + char c; +#ifdef SA_SIGINFO + kill(getpid(), SIGUSR1); +#endif + kill(getpid(), SIGALRM); + + do_read(fd[1], &c, 1); + fde_count++; +} + +/* This will only fire if the fd's returned from pipe() are bi-directional. */ +static void fde_handler_write_1(struct tevent_context *ev_ctx, struct tevent_fd *f, + uint16_t flags, void *private_data) +{ + int *fd = (int *)private_data; + char c = 0; + do_write(fd[0], &c, 1); +} + +static void finished_handler(struct tevent_context *ev_ctx, struct tevent_timer *te, + struct timeval tval, void *private_data) +{ + int *finished = (int *)private_data; + (*finished) = 1; +} + +static void count_handler(struct tevent_context *ev_ctx, struct tevent_signal *te, + int signum, int count, void *info, void *private_data) +{ + int *countp = (int *)private_data; + (*countp) += count; +} + +static bool test_event_context(struct torture_context *test, + const void *test_data) +{ + struct tevent_context *ev_ctx; + int fd[2] = { -1, -1 }; + const char *backend = (const char *)test_data; + int alarm_count=0, info_count=0; + 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; + int ret; + + ev_ctx = tevent_context_init_byname(test, backend); + if (ev_ctx == NULL) { + torture_comment(test, "event backend '%s' not supported\n", backend); + return true; + } + + torture_comment(test, "backend '%s' - %s\n", + backend, __FUNCTION__); + + /* reset globals */ + fde_count = 0; + + /* create a pipe */ + ret = pipe(fd); + torture_assert_int_equal(test, ret, 0, "pipe failed"); + + 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, fd); + + 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, fd); + + 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 + + t = timeval_current(); + while (!finished) { + errno = 0; + if (tevent_loop_once(ev_ctx) == -1) { + TALLOC_FREE(ev_ctx); + torture_fail(test, talloc_asprintf(test, "Failed event loop %s\n", strerror(errno))); + return false; + } + } + + talloc_free(fde_read_1); + talloc_free(fde_write_1); + talloc_free(fde_read); + talloc_free(fde_write); + + while (alarm_count < fde_count+1) { + if (tevent_loop_once(ev_ctx) == -1) { + break; + } + } + + torture_comment(test, "Got %.2f pipe events/sec\n", fde_count/timeval_elapsed(&t)); + +#ifdef SA_RESTART + talloc_free(se1); +#endif + + 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"); +#endif + + talloc_free(ev_ctx); + + 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... + */ + do_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; + int ret; + + 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; + + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, state.sock); + torture_assert(tctx, ret == 0, "socketpair() failed"); + + state.te = tevent_add_timer(state.ev, state.ev, + timeval_current_ofs(0,10000), + 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 >= PIPE_BUF) { + /* + * On Linux we become writable once we've read + * one byte. On Solaris we only become writable + * again once we've read 4096 bytes. PIPE_BUF + * is probably a safe bet to test against. + * + * 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); + + do_write(state.sock0.fd, &c, 1); + state.sock0.num_written++; + do_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; +} + +struct test_wrapper_state { + struct torture_context *tctx; + int num_events; + int num_wrap_handlers; +}; + +static bool test_wrapper_before_use(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; + return true; +} + +static void test_wrapper_after_use(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; +} + +static void test_wrapper_before_fd_handler(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + struct tevent_fd *fde, + uint16_t flags, + const char *handler_name, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; +} + +static void test_wrapper_after_fd_handler(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + struct tevent_fd *fde, + uint16_t flags, + const char *handler_name, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; +} + +static void test_wrapper_before_timer_handler(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + struct tevent_timer *te, + struct timeval requested_time, + struct timeval trigger_time, + const char *handler_name, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; +} + +static void test_wrapper_after_timer_handler(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + struct tevent_timer *te, + struct timeval requested_time, + struct timeval trigger_time, + const char *handler_name, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; +} + +static void test_wrapper_before_immediate_handler(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + struct tevent_immediate *im, + const char *handler_name, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; +} + +static void test_wrapper_after_immediate_handler(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + struct tevent_immediate *im, + const char *handler_name, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; +} + +static void test_wrapper_before_signal_handler(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + const char *handler_name, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; +} + +static void test_wrapper_after_signal_handler(struct tevent_context *wrap_ev, + void *private_data, + struct tevent_context *main_ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + const char *handler_name, + const char *location) +{ + struct test_wrapper_state *state = + talloc_get_type_abort(private_data, + struct test_wrapper_state); + + torture_comment(state->tctx, "%s\n", __func__); + state->num_wrap_handlers++; +} + +static const struct tevent_wrapper_ops test_wrapper_ops = { + .name = "test_wrapper", + .before_use = test_wrapper_before_use, + .after_use = test_wrapper_after_use, + .before_fd_handler = test_wrapper_before_fd_handler, + .after_fd_handler = test_wrapper_after_fd_handler, + .before_timer_handler = test_wrapper_before_timer_handler, + .after_timer_handler = test_wrapper_after_timer_handler, + .before_immediate_handler = test_wrapper_before_immediate_handler, + .after_immediate_handler = test_wrapper_after_immediate_handler, + .before_signal_handler = test_wrapper_before_signal_handler, + .after_signal_handler = test_wrapper_after_signal_handler, +}; + +static void test_wrapper_timer_handler(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval tv, + void *private_data) +{ + struct test_wrapper_state *state = + (struct test_wrapper_state *)private_data; + + + torture_comment(state->tctx, "timer handler\n"); + + state->num_events++; + talloc_free(te); + return; +} + +static void test_wrapper_fd_handler(struct tevent_context *ev, + struct tevent_fd *fde, + unsigned short fd_flags, + void *private_data) +{ + struct test_wrapper_state *state = + (struct test_wrapper_state *)private_data; + + torture_comment(state->tctx, "fd handler\n"); + + state->num_events++; + talloc_free(fde); + return; +} + +static void test_wrapper_immediate_handler(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_data) +{ + struct test_wrapper_state *state = + (struct test_wrapper_state *)private_data; + + state->num_events++; + talloc_free(im); + + torture_comment(state->tctx, "immediate handler\n"); + return; +} + +static void test_wrapper_signal_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + struct test_wrapper_state *state = + (struct test_wrapper_state *)private_data; + + torture_comment(state->tctx, "signal handler\n"); + + state->num_events++; + talloc_free(se); + return; +} + +static bool test_wrapper(struct torture_context *tctx, + const void *test_data) +{ + struct test_wrapper_state *state = NULL; + int sock[2] = { -1, -1}; + uint8_t c = 0; + const int num_events = 4; + const char *backend = (const char *)test_data; + struct tevent_context *ev = NULL; + struct tevent_context *wrap_ev = NULL; + struct tevent_fd *fde = NULL; + struct tevent_timer *te = NULL; + struct tevent_signal *se = NULL; + struct tevent_immediate *im = NULL; + int ret; + bool ok = false; + bool ret2; + + ev = tevent_context_init_byname(tctx, backend); + if (ev == NULL) { + torture_skip(tctx, talloc_asprintf(tctx, + "event backend '%s' not supported\n", + backend)); + return true; + } + + tevent_set_debug_stderr(ev); + torture_comment(tctx, "tevent backend '%s'\n", backend); + + wrap_ev = tevent_context_wrapper_create( + ev, ev, &test_wrapper_ops, &state, struct test_wrapper_state); + torture_assert_not_null_goto(tctx, wrap_ev, ok, done, + "tevent_context_wrapper_create failed\n"); + *state = (struct test_wrapper_state) { + .tctx = tctx, + }; + + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + torture_assert_goto(tctx, ret == 0, ok, done, "socketpair failed\n"); + + te = tevent_add_timer(wrap_ev, wrap_ev, + timeval_current_ofs(0, 0), + test_wrapper_timer_handler, state); + torture_assert_not_null_goto(tctx, te, ok, done, + "tevent_add_timer failed\n"); + + fde = tevent_add_fd(wrap_ev, wrap_ev, + sock[1], + TEVENT_FD_READ, + test_wrapper_fd_handler, + state); + torture_assert_not_null_goto(tctx, fde, ok, done, + "tevent_add_fd failed\n"); + + im = tevent_create_immediate(wrap_ev); + torture_assert_not_null_goto(tctx, im, ok, done, + "tevent_create_immediate failed\n"); + + se = tevent_add_signal(wrap_ev, wrap_ev, + SIGUSR1, + 0, + test_wrapper_signal_handler, + state); + torture_assert_not_null_goto(tctx, se, ok, done, + "tevent_add_signal failed\n"); + + do_write(sock[0], &c, 1); + kill(getpid(), SIGUSR1); + tevent_schedule_immediate(im, + wrap_ev, + test_wrapper_immediate_handler, + state); + + ret2 = tevent_context_push_use(wrap_ev); + torture_assert_goto(tctx, ret2, ok, done, "tevent_context_push_use(wrap_ev) failed\n"); + ret2 = tevent_context_push_use(ev); + torture_assert_goto(tctx, ret2, ok, pop_use, "tevent_context_push_use(ev) failed\n"); + tevent_context_pop_use(ev); + tevent_context_pop_use(wrap_ev); + + ret = tevent_loop_wait(ev); + torture_assert_int_equal_goto(tctx, ret, 0, ok, done, "tevent_loop_wait failed\n"); + + torture_comment(tctx, "Num events: %d\n", state->num_events); + torture_comment(tctx, "Num wrap handlers: %d\n", + state->num_wrap_handlers); + + torture_assert_int_equal_goto(tctx, state->num_events, num_events, ok, done, + "Wrong event count\n"); + torture_assert_int_equal_goto(tctx, state->num_wrap_handlers, + num_events*2+2, + ok, done, "Wrong wrapper count\n"); + + ok = true; + +done: + TALLOC_FREE(wrap_ev); + TALLOC_FREE(ev); + + if (sock[0] != -1) { + close(sock[0]); + } + if (sock[1] != -1) { + close(sock[1]); + } + return ok; +pop_use: + tevent_context_pop_use(wrap_ev); + goto done; +} + +static void test_free_wrapper_signal_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + struct torture_context *tctx = + talloc_get_type_abort(private_data, + struct torture_context); + + torture_comment(tctx, "signal handler\n"); + + talloc_free(se); + + /* + * signal handlers have highest priority in tevent, so this signal + * handler will always be started before the other handlers + * below. Freeing the (wrapper) event context here tests that the + * wrapper implementation correclty handles the wrapper ev going away + * with pending events. + */ + talloc_free(ev); + return; +} + +static void test_free_wrapper_fd_handler(struct tevent_context *ev, + struct tevent_fd *fde, + unsigned short fd_flags, + void *private_data) +{ + /* + * This should never be called as + * test_free_wrapper_signal_handler() + * already destroyed the wrapper tevent_context. + */ + abort(); +} + +static void test_free_wrapper_immediate_handler(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_data) +{ + /* + * This should never be called as + * test_free_wrapper_signal_handler() + * already destroyed the wrapper tevent_context. + */ + abort(); +} + +static void test_free_wrapper_timer_handler(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval tv, + void *private_data) +{ + /* + * This should never be called as + * test_free_wrapper_signal_handler() + * already destroyed the wrapper tevent_context. + */ + abort(); +} + +static bool test_free_wrapper(struct torture_context *tctx, + const void *test_data) +{ + struct test_wrapper_state *state = NULL; + int sock[2] = { -1, -1}; + uint8_t c = 0; + const char *backend = (const char *)test_data; + TALLOC_CTX *frame = talloc_stackframe(); + struct tevent_context *ev = NULL; + struct tevent_context *wrap_ev = NULL; + struct tevent_fd *fde = NULL; + struct tevent_timer *te = NULL; + struct tevent_signal *se = NULL; + struct tevent_immediate *im = NULL; + int ret; + bool ok = false; + + ev = tevent_context_init_byname(frame, backend); + if (ev == NULL) { + torture_skip(tctx, talloc_asprintf(tctx, + "event backend '%s' not supported\n", + backend)); + return true; + } + + tevent_set_debug_stderr(ev); + torture_comment(tctx, "tevent backend '%s'\n", backend); + + wrap_ev = tevent_context_wrapper_create( + ev, ev, &test_wrapper_ops, &state, struct test_wrapper_state); + torture_assert_not_null_goto(tctx, wrap_ev, ok, done, + "tevent_context_wrapper_create failed\n"); + *state = (struct test_wrapper_state) { + .tctx = tctx, + }; + + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sock); + torture_assert_goto(tctx, ret == 0, ok, done, "socketpair failed\n"); + + fde = tevent_add_fd(wrap_ev, frame, + sock[1], + TEVENT_FD_READ, + test_free_wrapper_fd_handler, + NULL); + torture_assert_not_null_goto(tctx, fde, ok, done, + "tevent_add_fd failed\n"); + + te = tevent_add_timer(wrap_ev, frame, + timeval_current_ofs(0, 0), + test_free_wrapper_timer_handler, NULL); + torture_assert_not_null_goto(tctx, te, ok, done, + "tevent_add_timer failed\n"); + + im = tevent_create_immediate(frame); + torture_assert_not_null_goto(tctx, im, ok, done, + "tevent_create_immediate failed\n"); + + se = tevent_add_signal(wrap_ev, frame, + SIGUSR1, + 0, + test_free_wrapper_signal_handler, + tctx); + torture_assert_not_null_goto(tctx, se, ok, done, + "tevent_add_signal failed\n"); + + do_write(sock[0], &c, 1); + kill(getpid(), SIGUSR1); + tevent_schedule_immediate(im, + wrap_ev, + test_free_wrapper_immediate_handler, + NULL); + + ret = tevent_loop_wait(ev); + torture_assert_goto(tctx, ret == 0, ok, done, "tevent_loop_wait failed\n"); + + ok = true; + +done: + TALLOC_FREE(frame); + + if (sock[0] != -1) { + close(sock[0]); + } + if (sock[1] != -1) { + close(sock[1]); + } + return ok; +} + +#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); + + do_write(fds[1], &c, 1); + + poll(NULL, 0, 100); + + test_event_threaded_lock(); + do_shutdown = true; + test_event_threaded_unlock(); + + do_write(fds[1], &c, 1); + + ret = pthread_join(poll_thread, NULL); + torture_assert(test, ret == 0, "pthread_join failed"); + + return true; +} + +#define NUM_TEVENT_THREADS 100 + +/* Ugly, but needed for torture_comment... */ +static struct torture_context *thread_test_ctx; +static pthread_t thread_map[NUM_TEVENT_THREADS]; +static unsigned thread_counter; + +/* Called in master thread context */ +static void callback_nowait(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_ptr) +{ + pthread_t *thread_id_ptr = + talloc_get_type_abort(private_ptr, pthread_t); + unsigned i; + + for (i = 0; i < NUM_TEVENT_THREADS; i++) { + if (pthread_equal(*thread_id_ptr, + thread_map[i])) { + break; + } + } + torture_comment(thread_test_ctx, + "Callback %u from thread %u\n", + thread_counter, + i); + thread_counter++; +} + +/* Blast the master tevent_context with a callback, no waiting. */ +static void *thread_fn_nowait(void *private_ptr) +{ + struct tevent_thread_proxy *master_tp = + talloc_get_type_abort(private_ptr, struct tevent_thread_proxy); + struct tevent_immediate *im; + pthread_t *thread_id_ptr; + + im = tevent_create_immediate(NULL); + if (im == NULL) { + return NULL; + } + thread_id_ptr = talloc(NULL, pthread_t); + if (thread_id_ptr == NULL) { + return NULL; + } + *thread_id_ptr = pthread_self(); + + tevent_thread_proxy_schedule(master_tp, + &im, + callback_nowait, + &thread_id_ptr); + return NULL; +} + +static void timeout_fn(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval tv, void *p) +{ + thread_counter = NUM_TEVENT_THREADS * 10; +} + +static bool test_multi_tevent_threaded(struct torture_context *test, + const void *test_data) +{ + unsigned i; + struct tevent_context *master_ev; + struct tevent_thread_proxy *tp; + + talloc_disable_null_tracking(); + + /* Ugly global stuff. */ + thread_test_ctx = test; + thread_counter = 0; + + master_ev = tevent_context_init(NULL); + if (master_ev == NULL) { + return false; + } + tevent_set_debug_stderr(master_ev); + + tp = tevent_thread_proxy_create(master_ev); + if (tp == NULL) { + torture_fail(test, + talloc_asprintf(test, + "tevent_thread_proxy_create failed\n")); + talloc_free(master_ev); + return false; + } + + for (i = 0; i < NUM_TEVENT_THREADS; i++) { + int ret = pthread_create(&thread_map[i], + NULL, + thread_fn_nowait, + tp); + if (ret != 0) { + torture_fail(test, + talloc_asprintf(test, + "Failed to create thread %i, %d\n", + i, ret)); + return false; + } + } + + /* Ensure we don't wait more than 10 seconds. */ + tevent_add_timer(master_ev, + master_ev, + timeval_current_ofs(10,0), + timeout_fn, + NULL); + + while (thread_counter < NUM_TEVENT_THREADS) { + int ret = tevent_loop_once(master_ev); + torture_assert(test, ret == 0, "tevent_loop_once failed"); + } + + torture_assert(test, thread_counter == NUM_TEVENT_THREADS, + "thread_counter fail\n"); + + talloc_free(master_ev); + return true; +} + +struct reply_state { + struct tevent_thread_proxy *reply_tp; + pthread_t thread_id; + int *p_finished; +}; + +static void thread_timeout_fn(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval tv, void *p) +{ + int *p_finished = (int *)p; + + *p_finished = 2; +} + +/* Called in child-thread context */ +static void thread_callback(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_ptr) +{ + struct reply_state *rsp = + talloc_get_type_abort(private_ptr, struct reply_state); + + talloc_steal(ev, rsp); + *rsp->p_finished = 1; +} + +/* Called in master thread context */ +static void master_callback(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_ptr) +{ + struct reply_state *rsp = + talloc_get_type_abort(private_ptr, struct reply_state); + unsigned i; + + talloc_steal(ev, rsp); + + for (i = 0; i < NUM_TEVENT_THREADS; i++) { + if (pthread_equal(rsp->thread_id, + thread_map[i])) { + break; + } + } + torture_comment(thread_test_ctx, + "Callback %u from thread %u\n", + thread_counter, + i); + /* Now reply to the thread ! */ + tevent_thread_proxy_schedule(rsp->reply_tp, + &im, + thread_callback, + &rsp); + + thread_counter++; +} + +static void *thread_fn_1(void *private_ptr) +{ + struct tevent_thread_proxy *master_tp = + talloc_get_type_abort(private_ptr, struct tevent_thread_proxy); + struct tevent_thread_proxy *tp; + struct tevent_immediate *im; + struct tevent_context *ev; + struct reply_state *rsp; + int finished = 0; + int ret; + + ev = tevent_context_init(NULL); + if (ev == NULL) { + return NULL; + } + + tp = tevent_thread_proxy_create(ev); + if (tp == NULL) { + talloc_free(ev); + return NULL; + } + + im = tevent_create_immediate(ev); + if (im == NULL) { + talloc_free(ev); + return NULL; + } + + rsp = talloc(ev, struct reply_state); + if (rsp == NULL) { + talloc_free(ev); + return NULL; + } + + rsp->thread_id = pthread_self(); + rsp->reply_tp = tp; + rsp->p_finished = &finished; + + /* Introduce a little randomness into the mix.. */ + usleep(random() % 7000); + + tevent_thread_proxy_schedule(master_tp, + &im, + master_callback, + &rsp); + + /* Ensure we don't wait more than 10 seconds. */ + tevent_add_timer(ev, + ev, + timeval_current_ofs(10,0), + thread_timeout_fn, + &finished); + + while (finished == 0) { + ret = tevent_loop_once(ev); + assert(ret == 0); + } + + if (finished > 1) { + /* Timeout ! */ + abort(); + } + + /* + * NB. We should talloc_free(ev) here, but if we do + * we currently get hit by helgrind Fix #323432 + * "When calling pthread_cond_destroy or pthread_mutex_destroy + * with initializers as argument Helgrind (incorrectly) reports errors." + * + * http://valgrind.10908.n7.nabble.com/Helgrind-3-9-0-false-positive- + * with-pthread-mutex-destroy-td47757.html + * + * Helgrind doesn't understand that the request/reply + * messages provide synchronization between the lock/unlock + * in tevent_thread_proxy_schedule(), and the pthread_destroy() + * when the struct tevent_thread_proxy object is talloc_free'd. + * + * As a work-around for now return ev for the parent thread to free. + */ + return ev; +} + +static bool test_multi_tevent_threaded_1(struct torture_context *test, + const void *test_data) +{ + unsigned i; + struct tevent_context *master_ev; + struct tevent_thread_proxy *master_tp; + int ret; + + talloc_disable_null_tracking(); + + /* Ugly global stuff. */ + thread_test_ctx = test; + thread_counter = 0; + + master_ev = tevent_context_init(NULL); + if (master_ev == NULL) { + return false; + } + tevent_set_debug_stderr(master_ev); + + master_tp = tevent_thread_proxy_create(master_ev); + if (master_tp == NULL) { + torture_fail(test, + talloc_asprintf(test, + "tevent_thread_proxy_create failed\n")); + talloc_free(master_ev); + return false; + } + + for (i = 0; i < NUM_TEVENT_THREADS; i++) { + ret = pthread_create(&thread_map[i], + NULL, + thread_fn_1, + master_tp); + if (ret != 0) { + torture_fail(test, + talloc_asprintf(test, + "Failed to create thread %i, %d\n", + i, ret)); + return false; + } + } + + while (thread_counter < NUM_TEVENT_THREADS) { + ret = tevent_loop_once(master_ev); + torture_assert(test, ret == 0, "tevent_loop_once failed"); + } + + /* Wait for all the threads to finish - join 'em. */ + for (i = 0; i < NUM_TEVENT_THREADS; i++) { + void *retval; + ret = pthread_join(thread_map[i], &retval); + torture_assert(test, ret == 0, "pthread_join failed"); + /* Free the child thread event context. */ + talloc_free(retval); + } + + talloc_free(master_ev); + return true; +} + +struct threaded_test_2 { + struct tevent_threaded_context *tctx; + struct tevent_immediate *im; + pthread_t thread_id; +}; + +static void master_callback_2(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_data); + +static void *thread_fn_2(void *private_data) +{ + struct threaded_test_2 *state = private_data; + + state->thread_id = pthread_self(); + + usleep(random() % 7000); + + tevent_threaded_schedule_immediate( + state->tctx, state->im, master_callback_2, state); + + return NULL; +} + +static void master_callback_2(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_data) +{ + struct threaded_test_2 *state = private_data; + int i; + + for (i = 0; i < NUM_TEVENT_THREADS; i++) { + if (pthread_equal(state->thread_id, thread_map[i])) { + break; + } + } + torture_comment(thread_test_ctx, + "Callback_2 %u from thread %u\n", + thread_counter, + i); + thread_counter++; +} + +static bool test_multi_tevent_threaded_2(struct torture_context *test, + const void *test_data) +{ + unsigned i; + + struct tevent_context *ev; + struct tevent_threaded_context *tctx; + int ret; + + thread_test_ctx = test; + thread_counter = 0; + + ev = tevent_context_init(test); + torture_assert(test, ev != NULL, "tevent_context_init failed"); + + /* + * tevent_re_initialise used to have a bug where it did not + * re-initialise the thread support after taking it + * down. Exercise that code path. + */ + ret = tevent_re_initialise(ev); + torture_assert(test, ret == 0, "tevent_re_initialise failed"); + + tctx = tevent_threaded_context_create(ev, ev); + torture_assert(test, tctx != NULL, + "tevent_threaded_context_create failed"); + + for (i=0; i<NUM_TEVENT_THREADS; i++) { + struct threaded_test_2 *state; + + state = talloc(ev, struct threaded_test_2); + torture_assert(test, state != NULL, "talloc failed"); + + state->tctx = tctx; + state->im = tevent_create_immediate(state); + torture_assert(test, state->im != NULL, + "tevent_create_immediate failed"); + + ret = pthread_create(&thread_map[i], NULL, thread_fn_2, state); + torture_assert(test, ret == 0, "pthread_create failed"); + } + + while (thread_counter < NUM_TEVENT_THREADS) { + ret = tevent_loop_once(ev); + torture_assert(test, ret == 0, "tevent_loop_once failed"); + } + + /* Wait for all the threads to finish - join 'em. */ + for (i = 0; i < NUM_TEVENT_THREADS; i++) { + void *retval; + ret = pthread_join(thread_map[i], &retval); + torture_assert(test, ret == 0, "pthread_join failed"); + /* Free the child thread event context. */ + } + + talloc_free(tctx); + talloc_free(ev); + return true; +} + +struct test_cached_pid_thread_state { + pid_t thread_cached_pid; + pid_t thread_pid; +}; + +static void *test_cached_pid_thread(void *private_data) +{ + struct test_cached_pid_thread_state *state = + (struct test_cached_pid_thread_state *)private_data; + + state->thread_cached_pid = tevent_cached_getpid(); + state->thread_pid = getpid(); + + return NULL; +} +#endif + +static bool test_cached_pid(struct torture_context *test, + const void *test_data) +{ + pid_t parent_pid = getpid(); + pid_t child_pid; + pid_t finished_pid; + int child_status; + + torture_assert(test, tevent_cached_getpid() == parent_pid, "tevent_cached_getpid()"); + +#ifdef HAVE_PTHREAD + { + struct test_cached_pid_thread_state state = { .thread_cached_pid = -1, }; + pthread_t thread; + void *retval = NULL; + int ret; + + ret = pthread_create(&thread, NULL, test_cached_pid_thread, &state); + torture_assert(test, ret == 0, "pthread_create failed"); + + ret = pthread_join(thread, &retval); + torture_assert(test, ret == 0, "pthread_join failed"); + + torture_assert(test, state.thread_pid == parent_pid, "getpid() in thread"); + torture_assert(test, state.thread_cached_pid == parent_pid, "tevent_cached_getpid() in thread"); + } +#endif /* HAVE_PTHREAD */ + + child_pid = fork(); + if (child_pid == 0) { + /* child */ + pid_t pid = getpid(); + pid_t cached_pid = tevent_cached_getpid(); + + if (parent_pid == pid) { + exit(1); + } + if (pid != cached_pid) { + exit(2); + } + exit(0); + } + torture_assert(test, child_pid > 0, "fork failed"); + + finished_pid = waitpid(child_pid, &child_status, 0); + torture_assert(test, finished_pid == child_pid, "wrong child"); + torture_assert(test, child_status == 0, "child_status"); + + return true; +} + +struct torture_suite *torture_local_event(TALLOC_CTX *mem_ctx) +{ + struct torture_suite *suite = torture_suite_create(mem_ctx, "event"); + const char **list = tevent_backend_list(suite); + int i; + + for (i=0;list && list[i];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_simple_tcase_const(backend_suite, + "wrapper", + test_wrapper, + (const void *)list[i]); + torture_suite_add_simple_tcase_const(backend_suite, + "free_wrapper", + test_free_wrapper, + (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); + + torture_suite_add_simple_tcase_const(suite, "multi_tevent_threaded", + test_multi_tevent_threaded, + NULL); + + torture_suite_add_simple_tcase_const(suite, "multi_tevent_threaded_1", + test_multi_tevent_threaded_1, + NULL); + + torture_suite_add_simple_tcase_const(suite, "multi_tevent_threaded_2", + test_multi_tevent_threaded_2, + NULL); + +#endif + + torture_suite_add_simple_tcase_const(suite, "tevent_cached_getpid", + test_cached_pid, + NULL); + + return suite; +} diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c new file mode 100644 index 0000000..262fdaa --- /dev/null +++ b/lib/tevent/tevent.c @@ -0,0 +1,1090 @@ +/* + Unix SMB/CIFS implementation. + main select loop and event handling + Copyright (C) Andrew Tridgell 2003 + Copyright (C) Stefan Metzmacher 2009 + + ** 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/>. +*/ + +/* + PLEASE READ THIS BEFORE MODIFYING! + + This module is a general abstraction for the main select loop and + event handling. Do not ever put any localised hacks in here, instead + register one of the possible event types and implement that event + somewhere else. + + There are 2 types of event handling that are handled in this module: + + 1) a file descriptor becoming readable or writeable. This is mostly + used for network sockets, but can be used for any type of file + descriptor. You may only register one handler for each file + descriptor/io combination or you will get unpredictable results + (this means that you can have a handler for read events, and a + separate handler for write events, but not two handlers that are + both handling read events) + + 2) a timed event. You can register an event that happens at a + specific time. You can register as many of these as you + like. They are single shot - add a new timed event in the event + handler to get another event. + + To setup a set of events you first need to create a event_context + structure using the function tevent_context_init(); This returns a + 'struct tevent_context' that you use in all subsequent calls. + + After that you can add/remove events that you are interested in + using tevent_add_*() and talloc_free() + + Finally, you call tevent_loop_wait_once() to block waiting for one of the + events to occor or tevent_loop_wait() which will loop + forever. + +*/ +#include "replace.h" +#include "system/filesys.h" +#ifdef HAVE_PTHREAD +#include "system/threads.h" +#endif +#define TEVENT_DEPRECATED 1 +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" +#ifdef HAVE_EVENTFD +#include <sys/eventfd.h> +#endif + +struct tevent_ops_list { + struct tevent_ops_list *next, *prev; + const char *name; + const struct tevent_ops *ops; +}; + +/* list of registered event backends */ +static struct tevent_ops_list *tevent_backends = NULL; +static char *tevent_default_backend = NULL; + +/* + register an events backend +*/ +bool tevent_register_backend(const char *name, const struct tevent_ops *ops) +{ + struct tevent_ops_list *e; + + for (e = tevent_backends; e != NULL; e = e->next) { + if (0 == strcmp(e->name, name)) { + /* already registered, skip it */ + return true; + } + } + + e = talloc(NULL, struct tevent_ops_list); + if (e == NULL) return false; + + e->name = name; + e->ops = ops; + DLIST_ADD(tevent_backends, e); + + return true; +} + +/* + set the default event backend + */ +void tevent_set_default_backend(const char *backend) +{ + talloc_free(tevent_default_backend); + tevent_default_backend = talloc_strdup(NULL, backend); +} + +/* + initialise backends if not already done +*/ +static void tevent_backend_init(void) +{ + static bool done; + + if (done) { + return; + } + + done = true; + + tevent_poll_init(); + tevent_poll_mt_init(); +#if defined(HAVE_EPOLL) + tevent_epoll_init(); +#elif defined(HAVE_SOLARIS_PORTS) + tevent_port_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; +} + +/* + list available backends +*/ +const char **tevent_backend_list(TALLOC_CTX *mem_ctx) +{ + const char **list = NULL; + struct tevent_ops_list *e; + size_t idx = 0; + + tevent_backend_init(); + + for (e=tevent_backends;e;e=e->next) { + idx += 1; + } + + list = talloc_zero_array(mem_ctx, const char *, idx+1); + if (list == NULL) { + return NULL; + } + + idx = 0; + for (e=tevent_backends;e;e=e->next) { + list[idx] = talloc_strdup(list, e->name); + if (list[idx] == NULL) { + TALLOC_FREE(list); + return NULL; + } + idx += 1; + } + + return list; +} + +static void tevent_common_wakeup_fini(struct tevent_context *ev); + +#ifdef HAVE_PTHREAD + +static pthread_mutex_t tevent_contexts_mutex = PTHREAD_MUTEX_INITIALIZER; +static struct tevent_context *tevent_contexts = NULL; +static pthread_once_t tevent_atfork_initialized = PTHREAD_ONCE_INIT; +static pid_t tevent_cached_global_pid = 0; + +static void tevent_atfork_prepare(void) +{ + struct tevent_context *ev; + int ret; + + ret = pthread_mutex_lock(&tevent_contexts_mutex); + if (ret != 0) { + abort(); + } + + for (ev = tevent_contexts; ev != NULL; ev = ev->next) { + struct tevent_threaded_context *tctx; + + for (tctx = ev->threaded_contexts; tctx != NULL; + tctx = tctx->next) { + ret = pthread_mutex_lock(&tctx->event_ctx_mutex); + if (ret != 0) { + tevent_abort(ev, "pthread_mutex_lock failed"); + } + } + + ret = pthread_mutex_lock(&ev->scheduled_mutex); + if (ret != 0) { + tevent_abort(ev, "pthread_mutex_lock failed"); + } + } +} + +static void tevent_atfork_parent(void) +{ + struct tevent_context *ev; + int ret; + + for (ev = DLIST_TAIL(tevent_contexts); ev != NULL; + ev = DLIST_PREV(ev)) { + struct tevent_threaded_context *tctx; + + ret = pthread_mutex_unlock(&ev->scheduled_mutex); + if (ret != 0) { + tevent_abort(ev, "pthread_mutex_unlock failed"); + } + + for (tctx = DLIST_TAIL(ev->threaded_contexts); tctx != NULL; + tctx = DLIST_PREV(tctx)) { + ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); + if (ret != 0) { + tevent_abort( + ev, "pthread_mutex_unlock failed"); + } + } + } + + ret = pthread_mutex_unlock(&tevent_contexts_mutex); + if (ret != 0) { + abort(); + } +} + +static void tevent_atfork_child(void) +{ + struct tevent_context *ev; + int ret; + + tevent_cached_global_pid = getpid(); + + for (ev = DLIST_TAIL(tevent_contexts); ev != NULL; + ev = DLIST_PREV(ev)) { + struct tevent_threaded_context *tctx; + + for (tctx = DLIST_TAIL(ev->threaded_contexts); tctx != NULL; + tctx = DLIST_PREV(tctx)) { + tctx->event_ctx = NULL; + + ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); + if (ret != 0) { + tevent_abort( + ev, "pthread_mutex_unlock failed"); + } + } + + ev->threaded_contexts = NULL; + + ret = pthread_mutex_unlock(&ev->scheduled_mutex); + if (ret != 0) { + tevent_abort(ev, "pthread_mutex_unlock failed"); + } + } + + ret = pthread_mutex_unlock(&tevent_contexts_mutex); + if (ret != 0) { + abort(); + } +} + +static void tevent_prep_atfork(void) +{ + int ret; + + ret = pthread_atfork(tevent_atfork_prepare, + tevent_atfork_parent, + tevent_atfork_child); + if (ret != 0) { + abort(); + } + + tevent_cached_global_pid = getpid(); +} + +#endif + +static int tevent_init_globals(void) +{ +#ifdef HAVE_PTHREAD + int ret; + + ret = pthread_once(&tevent_atfork_initialized, tevent_prep_atfork); + if (ret != 0) { + return ret; + } +#endif + + return 0; +} + +_PUBLIC_ pid_t tevent_cached_getpid(void) +{ +#ifdef HAVE_PTHREAD + tevent_init_globals(); +#ifdef TEVENT_VERIFY_CACHED_GETPID + if (tevent_cached_global_pid != getpid()) { + tevent_abort(NULL, "tevent_cached_global_pid invalid"); + } +#endif + if (tevent_cached_global_pid != 0) { + return tevent_cached_global_pid; + } +#endif + return getpid(); +} + +int tevent_common_context_destructor(struct tevent_context *ev) +{ + struct tevent_fd *fd, *fn; + struct tevent_timer *te, *tn; + struct tevent_immediate *ie, *in; + struct tevent_signal *se, *sn; + struct tevent_wrapper_glue *gl, *gn; +#ifdef HAVE_PTHREAD + int ret; +#endif + + if (ev->wrapper.glue != NULL) { + tevent_abort(ev, + "tevent_common_context_destructor() active on wrapper"); + } + +#ifdef HAVE_PTHREAD + ret = pthread_mutex_lock(&tevent_contexts_mutex); + if (ret != 0) { + abort(); + } + + DLIST_REMOVE(tevent_contexts, ev); + + ret = pthread_mutex_unlock(&tevent_contexts_mutex); + if (ret != 0) { + abort(); + } + + while (ev->threaded_contexts != NULL) { + struct tevent_threaded_context *tctx = ev->threaded_contexts; + + ret = pthread_mutex_lock(&tctx->event_ctx_mutex); + if (ret != 0) { + abort(); + } + + /* + * Indicate to the thread that the tevent_context is + * gone. The counterpart of this is in + * _tevent_threaded_schedule_immediate, there we read + * this under the threaded_context's mutex. + */ + + tctx->event_ctx = NULL; + + ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); + if (ret != 0) { + abort(); + } + + DLIST_REMOVE(ev->threaded_contexts, tctx); + } + + ret = pthread_mutex_destroy(&ev->scheduled_mutex); + if (ret != 0) { + abort(); + } +#endif + + for (gl = ev->wrapper.list; gl; gl = gn) { + gn = gl->next; + + gl->main_ev = NULL; + DLIST_REMOVE(ev->wrapper.list, gl); + } + + tevent_common_wakeup_fini(ev); + + for (fd = ev->fd_events; fd; fd = fn) { + fn = fd->next; + tevent_trace_fd_callback(fd->event_ctx, fd, TEVENT_EVENT_TRACE_DETACH); + fd->wrapper = NULL; + fd->event_ctx = NULL; + DLIST_REMOVE(ev->fd_events, fd); + } + + ev->last_zero_timer = NULL; + for (te = ev->timer_events; te; te = tn) { + tn = te->next; + tevent_trace_timer_callback(te->event_ctx, te, TEVENT_EVENT_TRACE_DETACH); + te->wrapper = NULL; + te->event_ctx = NULL; + DLIST_REMOVE(ev->timer_events, te); + } + + for (ie = ev->immediate_events; ie; ie = in) { + in = ie->next; + tevent_trace_immediate_callback(ie->event_ctx, ie, TEVENT_EVENT_TRACE_DETACH); + ie->wrapper = NULL; + ie->event_ctx = NULL; + ie->cancel_fn = NULL; + DLIST_REMOVE(ev->immediate_events, ie); + } + + for (se = ev->signal_events; se; se = sn) { + sn = se->next; + tevent_trace_signal_callback(se->event_ctx, se, TEVENT_EVENT_TRACE_DETACH); + se->wrapper = NULL; + se->event_ctx = NULL; + DLIST_REMOVE(ev->signal_events, se); + /* + * This is important, Otherwise signals + * are handled twice in child. eg, SIGHUP. + * one added in parent, and another one in + * the child. -- BoYang + */ + tevent_cleanup_pending_signal_handlers(se); + } + + /* removing nesting hook or we get an abort when nesting is + * not allowed. -- SSS + * Note that we need to leave the allowed flag at its current + * value, otherwise the use in tevent_re_initialise() will + * leave the event context with allowed forced to false, which + * will break users that expect nesting to be allowed + */ + ev->nesting.level = 0; + ev->nesting.hook_fn = NULL; + ev->nesting.hook_private = NULL; + + return 0; +} + +static int tevent_common_context_constructor(struct tevent_context *ev) +{ + int ret; + + ret = tevent_init_globals(); + if (ret != 0) { + return ret; + } + +#ifdef HAVE_PTHREAD + + ret = pthread_mutex_init(&ev->scheduled_mutex, NULL); + if (ret != 0) { + return ret; + } + + ret = pthread_mutex_lock(&tevent_contexts_mutex); + if (ret != 0) { + pthread_mutex_destroy(&ev->scheduled_mutex); + return ret; + } + + DLIST_ADD(tevent_contexts, ev); + + ret = pthread_mutex_unlock(&tevent_contexts_mutex); + if (ret != 0) { + abort(); + } +#endif + + talloc_set_destructor(ev, tevent_common_context_destructor); + + return 0; +} + +void tevent_common_check_double_free(TALLOC_CTX *ptr, const char *reason) +{ + void *parent_ptr = talloc_parent(ptr); + size_t parent_blocks = talloc_total_blocks(parent_ptr); + + if (parent_ptr != NULL && parent_blocks == 0) { + /* + * This is an implicit talloc free, as we still have a parent + * but it's already being destroyed. Note that + * talloc_total_blocks(ptr) also just returns 0 if a + * talloc_free(ptr) is still in progress of freeing all + * children. + */ + return; + } + + tevent_abort(NULL, reason); +} + +/* + create a event_context structure for a specific implemementation. + This must be the first events call, and all subsequent calls pass + this event_context as the first element. Event handlers also + receive this as their first argument. + + This function is for allowing third-party-applications to hook in gluecode + to their own event loop code, so that they can make async usage of our client libs + + NOTE: use tevent_context_init() inside of samba! +*/ +struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx, + const struct tevent_ops *ops, + void *additional_data) +{ + struct tevent_context *ev; + int ret; + + ev = talloc_zero(mem_ctx, struct tevent_context); + if (!ev) return NULL; + + ret = tevent_common_context_constructor(ev); + if (ret != 0) { + talloc_free(ev); + return NULL; + } + + ev->ops = ops; + ev->additional_data = additional_data; + + ret = ev->ops->context_init(ev); + if (ret != 0) { + talloc_free(ev); + return NULL; + } + + return ev; +} + +/* + create a event_context structure. This must be the first events + call, and all subsequent calls pass this event_context as the first + element. Event handlers also receive this as their first argument. +*/ +struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx, + const char *name) +{ + const struct tevent_ops *ops; + + ops = tevent_find_ops_byname(name); + if (ops == NULL) { + return NULL; + } + + return tevent_context_init_ops(mem_ctx, ops, NULL); +} + + +/* + create a event_context structure. This must be the first events + call, and all subsequent calls pass this event_context as the first + element. Event handlers also receive this as their first argument. +*/ +struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx) +{ + return tevent_context_init_byname(mem_ctx, NULL); +} + +/* + add a fd based event + return NULL on failure (memory allocation error) +*/ +struct tevent_fd *_tevent_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) +{ + return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data, + handler_name, location); +} + +/* + set a close function on the fd event +*/ +void tevent_fd_set_close_fn(struct tevent_fd *fde, + tevent_fd_close_fn_t close_fn) +{ + if (!fde) return; + if (!fde->event_ctx) return; + fde->event_ctx->ops->set_fd_close_fn(fde, close_fn); +} + +static void tevent_fd_auto_close_fn(struct tevent_context *ev, + struct tevent_fd *fde, + int fd, + void *private_data) +{ + close(fd); +} + +void tevent_fd_set_auto_close(struct tevent_fd *fde) +{ + tevent_fd_set_close_fn(fde, tevent_fd_auto_close_fn); +} + +/* + return the fd event flags +*/ +uint16_t tevent_fd_get_flags(struct tevent_fd *fde) +{ + if (!fde) return 0; + if (!fde->event_ctx) return 0; + return fde->event_ctx->ops->get_fd_flags(fde); +} + +/* + set the fd event flags +*/ +void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags) +{ + if (!fde) return; + if (!fde->event_ctx) return; + fde->event_ctx->ops->set_fd_flags(fde, flags); +} + +bool tevent_signal_support(struct tevent_context *ev) +{ + if (ev->ops->add_signal) { + return true; + } + return false; +} + +static void (*tevent_abort_fn)(const char *reason); + +void tevent_set_abort_fn(void (*abort_fn)(const char *reason)) +{ + tevent_abort_fn = abort_fn; +} + +void tevent_abort(struct tevent_context *ev, const char *reason) +{ + if (ev != NULL) { + tevent_debug(ev, TEVENT_DEBUG_FATAL, + "abort: %s\n", reason); + } + + if (!tevent_abort_fn) { + abort(); + } + + tevent_abort_fn(reason); +} + +/* + add a timer event + return NULL on failure +*/ +struct tevent_timer *_tevent_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) +{ + return ev->ops->add_timer(ev, mem_ctx, next_event, handler, private_data, + handler_name, location); +} + +/* + allocate an immediate event + return NULL on failure (memory allocation error) +*/ +struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx, + const char *location) +{ + struct tevent_immediate *im; + + im = talloc(mem_ctx, struct tevent_immediate); + if (im == NULL) return NULL; + + *im = (struct tevent_immediate) { .create_location = location }; + + return im; +} + +/* + schedule an immediate event +*/ +void _tevent_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) +{ + ev->ops->schedule_immediate(im, ev, handler, private_data, + handler_name, location); +} + +/* + add a signal event + + sa_flags are flags to sigaction(2) + + return NULL on failure +*/ +struct tevent_signal *_tevent_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) +{ + return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data, + handler_name, location); +} + +void tevent_loop_allow_nesting(struct tevent_context *ev) +{ + if (ev->wrapper.glue != NULL) { + tevent_abort(ev, "tevent_loop_allow_nesting() on wrapper"); + return; + } + + if (ev->wrapper.list != NULL) { + tevent_abort(ev, "tevent_loop_allow_nesting() with wrapper"); + return; + } + + ev->nesting.allowed = true; +} + +void tevent_loop_set_nesting_hook(struct tevent_context *ev, + tevent_nesting_hook hook, + void *private_data) +{ + 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 + we cannot support two different nesting hooks at the + same time. */ + tevent_abort(ev, "tevent: Violation of nesting hook rules\n"); + } + ev->nesting.hook_fn = hook; + ev->nesting.hook_private = private_data; +} + +static void tevent_abort_nesting(struct tevent_context *ev, const char *location) +{ + const char *reason; + + reason = talloc_asprintf(NULL, "tevent_loop_once() nesting at %s", + location); + if (!reason) { + reason = "tevent_loop_once() nesting"; + } + + tevent_abort(ev, reason); +} + +/* + do a single event loop using the events defined in ev +*/ +int _tevent_loop_once(struct tevent_context *ev, const char *location) +{ + int ret; + void *nesting_stack_ptr = NULL; + + ev->nesting.level++; + + if (ev->nesting.level > 1) { + if (!ev->nesting.allowed) { + tevent_abort_nesting(ev, location); + errno = ELOOP; + return -1; + } + } + if (ev->nesting.level > 0) { + if (ev->nesting.hook_fn) { + int ret2; + ret2 = ev->nesting.hook_fn(ev, + ev->nesting.hook_private, + ev->nesting.level, + true, + (void *)&nesting_stack_ptr, + location); + if (ret2 != 0) { + ret = ret2; + goto done; + } + } + } + + 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) { + int ret2; + ret2 = ev->nesting.hook_fn(ev, + ev->nesting.hook_private, + ev->nesting.level, + false, + (void *)&nesting_stack_ptr, + location); + if (ret2 != 0) { + ret = ret2; + goto done; + } + } + } + +done: + ev->nesting.level--; + return ret; +} + +/* + this is a performance optimization for the samba4 nested event loop problems +*/ +int _tevent_loop_until(struct tevent_context *ev, + bool (*finished)(void *private_data), + void *private_data, + const char *location) +{ + int ret = 0; + void *nesting_stack_ptr = NULL; + + ev->nesting.level++; + + if (ev->nesting.level > 1) { + if (!ev->nesting.allowed) { + tevent_abort_nesting(ev, location); + errno = ELOOP; + return -1; + } + } + if (ev->nesting.level > 0) { + if (ev->nesting.hook_fn) { + int ret2; + ret2 = ev->nesting.hook_fn(ev, + ev->nesting.hook_private, + ev->nesting.level, + true, + (void *)&nesting_stack_ptr, + location); + if (ret2 != 0) { + ret = ret2; + goto done; + } + } + } + + 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; + } + } + + if (ev->nesting.level > 0) { + if (ev->nesting.hook_fn) { + int ret2; + ret2 = ev->nesting.hook_fn(ev, + ev->nesting.hook_private, + ev->nesting.level, + false, + (void *)&nesting_stack_ptr, + location); + if (ret2 != 0) { + ret = ret2; + goto done; + } + } + } + +done: + ev->nesting.level--; + return ret; +} + +bool tevent_common_have_events(struct tevent_context *ev) +{ + if (ev->fd_events != NULL) { + if (ev->fd_events != ev->wakeup_fde) { + return true; + } + if (ev->fd_events->next != NULL) { + return true; + } + + /* + * At this point we just have the wakeup pipe event as + * the only fd_event. That one does not count as a + * regular event, so look at the other event types. + */ + } + + return ((ev->timer_events != NULL) || + (ev->immediate_events != NULL) || + (ev->signal_events != NULL)); +} + +/* + return on failure or (with 0) if all fd events are removed +*/ +int tevent_common_loop_wait(struct tevent_context *ev, + const char *location) +{ + /* + * loop as long as we have events pending + */ + while (tevent_common_have_events(ev)) { + 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, + "tevent_common_loop_wait() out of events\n"); + return 0; +} + +/* + return on failure or (with 0) if all fd events are removed +*/ +int _tevent_loop_wait(struct tevent_context *ev, const char *location) +{ + return ev->ops->loop_wait(ev, 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() + + zero is returned on success, non-zero on failure +*/ +int tevent_re_initialise(struct tevent_context *ev) +{ + tevent_common_context_destructor(ev); + + tevent_common_context_constructor(ev); + + return ev->ops->context_init(ev); +} + +static void wakeup_pipe_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, void *_private) +{ + ssize_t ret; + + do { + /* + * This is the boilerplate for eventfd, but it works + * for pipes too. And as we don't care about the data + * we read, we're fine. + */ + uint64_t val; + ret = read(fde->fd, &val, sizeof(val)); + } while (ret == -1 && errno == EINTR); +} + +/* + * Initialize the wakeup pipe and pipe fde + */ + +int tevent_common_wakeup_init(struct tevent_context *ev) +{ + int ret, read_fd; + + if (ev->wakeup_fde != NULL) { + return 0; + } + +#ifdef HAVE_EVENTFD + ret = eventfd(0, EFD_NONBLOCK); + if (ret == -1) { + return errno; + } + read_fd = ev->wakeup_fd = ret; +#else + { + int pipe_fds[2]; + ret = pipe(pipe_fds); + if (ret == -1) { + return errno; + } + ev->wakeup_fd = pipe_fds[1]; + ev->wakeup_read_fd = pipe_fds[0]; + + ev_set_blocking(ev->wakeup_fd, false); + ev_set_blocking(ev->wakeup_read_fd, false); + + read_fd = ev->wakeup_read_fd; + } +#endif + + ev->wakeup_fde = tevent_add_fd(ev, ev, read_fd, TEVENT_FD_READ, + wakeup_pipe_handler, NULL); + if (ev->wakeup_fde == NULL) { + close(ev->wakeup_fd); +#ifndef HAVE_EVENTFD + close(ev->wakeup_read_fd); +#endif + return ENOMEM; + } + + return 0; +} + +int tevent_common_wakeup_fd(int fd) +{ + ssize_t ret; + + do { +#ifdef HAVE_EVENTFD + uint64_t val = 1; + ret = write(fd, &val, sizeof(val)); +#else + char c = '\0'; + ret = write(fd, &c, 1); +#endif + } while ((ret == -1) && (errno == EINTR)); + + return 0; +} + +int tevent_common_wakeup(struct tevent_context *ev) +{ + if (ev->wakeup_fde == NULL) { + return ENOTCONN; + } + + return tevent_common_wakeup_fd(ev->wakeup_fd); +} + +static void tevent_common_wakeup_fini(struct tevent_context *ev) +{ + if (ev->wakeup_fde == NULL) { + return; + } + + TALLOC_FREE(ev->wakeup_fde); + + close(ev->wakeup_fd); +#ifndef HAVE_EVENTFD + close(ev->wakeup_read_fd); +#endif +} diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h new file mode 100644 index 0000000..656df25 --- /dev/null +++ b/lib/tevent/tevent.h @@ -0,0 +1,2796 @@ +/* + Unix SMB/CIFS implementation. + + generalised event loop handling + + Copyright (C) Andrew Tridgell 2005 + Copyright (C) Stefan Metzmacher 2005-2009 + Copyright (C) Volker Lendecke 2008 + + ** 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/>. +*/ + +#ifndef __TEVENT_H__ +#define __TEVENT_H__ + +#include <stdint.h> +#include <talloc.h> +#include <sys/time.h> +#include <sys/types.h> +#include <stdbool.h> + +/* for old gcc releases that don't have the feature test macro __has_attribute */ +#ifndef __has_attribute +#define __has_attribute(x) 0 +#endif + + +struct tevent_context; +struct tevent_ops; +struct tevent_fd; +struct tevent_timer; +struct tevent_immediate; +struct tevent_signal; +struct tevent_thread_proxy; +struct tevent_threaded_context; + +/** + * @defgroup tevent The tevent API + * + * The tevent low-level API + * + * This API provides the public interface to manage events in the tevent + * mainloop. Functions are provided for managing low-level events such + * as timer events, fd events and signal handling. + * + * @{ + */ + +/* event handler types */ +/** + * Called when a file descriptor monitored by tevent has + * data to be read or written on it. + */ +typedef void (*tevent_fd_handler_t)(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data); + +/** + * Called when tevent is ceasing the monitoring of a file descriptor. + */ +typedef void (*tevent_fd_close_fn_t)(struct tevent_context *ev, + struct tevent_fd *fde, + int fd, + void *private_data); + +/** + * Called when a tevent timer has fired. + */ +typedef void (*tevent_timer_handler_t)(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval current_time, + void *private_data); + +/** + * Called when a tevent immediate event is invoked. + */ +typedef void (*tevent_immediate_handler_t)(struct tevent_context *ctx, + struct tevent_immediate *im, + void *private_data); + +/** + * Called after tevent detects the specified signal. + */ +typedef void (*tevent_signal_handler_t)(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data); + +/** + * @brief Create a event_context structure. + * + * This must be the first events call, and all subsequent calls pass this + * event_context as the first element. Event handlers also receive this as + * their first argument. + * + * @param[in] mem_ctx The memory context to use. + * + * @return An allocated tevent context, NULL on error. + * + * @see tevent_context_init() + */ +struct tevent_context *tevent_context_init(TALLOC_CTX *mem_ctx); + +/** + * @brief Create a event_context structure and select a specific backend. + * + * This must be the first events call, and all subsequent calls pass this + * event_context as the first element. Event handlers also receive this as + * their first argument. + * + * @param[in] mem_ctx The memory context to use. + * + * @param[in] name The name of the backend to use. + * + * @return An allocated tevent context, NULL on error. + */ +struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx, const char *name); + +/** + * @brief Create a custom event context + * + * @param[in] mem_ctx The memory context to use. + * @param[in] ops The function pointer table of the backend. + * @param[in] additional_data The additional/private data to this instance + * + * @return An allocated tevent context, NULL on error. + * + */ +struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx, + const struct tevent_ops *ops, + void *additional_data); + +/** + * @brief List available backends. + * + * @param[in] mem_ctx The memory context to use. + * + * @return A string vector with a terminating NULL element, NULL + * on error. + */ +const char **tevent_backend_list(TALLOC_CTX *mem_ctx); + +/** + * @brief Set the default tevent backend. + * + * @param[in] backend The name of the backend to set. + */ +void tevent_set_default_backend(const char *backend); + +#ifdef DOXYGEN +/** + * @brief Add a file descriptor based event. + * + * @param[in] ev The event context to work on. + * + * @param[in] mem_ctx The talloc memory context to use. + * + * @param[in] fd The file descriptor to base the event on. + * + * @param[in] flags #TEVENT_FD_READ or #TEVENT_FD_WRITE + * + * @param[in] handler The callback handler for the event. + * + * @param[in] private_data The private data passed to the callback handler. + * + * @return The file descriptor based event, NULL on error. + * + * @note To cancel the monitoring of a file descriptor, call talloc_free() + * on the object returned by this function. + * + * @note The caller should avoid closing the file descriptor before + * calling talloc_free()! Otherwise the behaviour is undefined which + * might result in crashes. See https://bugzilla.samba.org/show_bug.cgi?id=11141 + * for an example. + */ +struct tevent_fd *tevent_add_fd(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int fd, + uint16_t flags, + tevent_fd_handler_t handler, + void *private_data); +#else +struct tevent_fd *_tevent_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); +#define tevent_add_fd(ev, mem_ctx, fd, flags, handler, private_data) \ + _tevent_add_fd(ev, mem_ctx, fd, flags, handler, private_data, \ + #handler, __location__) +#endif + +/** + * @brief Associate a custom tag with the event. + * + * This tag can be then retrieved with tevent_fd_get_tag() + * + * @param[in] fde The file descriptor event. + * + * @param[in] tag Custom tag. + */ +void tevent_fd_set_tag(struct tevent_fd *fde, uint64_t tag); + +/** + * @brief Get custom event tag. + */ +uint64_t tevent_fd_get_tag(const struct tevent_fd *fde); + +#ifdef DOXYGEN +/** + * @brief Add a timed event + * + * @param[in] ev The event context to work on. + * + * @param[in] mem_ctx The talloc memory context to use. + * + * @param[in] next_event Timeval specifying the absolute time to fire this + * event. This is not an offset. + * + * @param[in] handler The callback handler for the event. + * + * @param[in] private_data The private data passed to the callback handler. + * + * @return The newly-created timer event, or NULL on error. + * + * @note To cancel a timer event before it fires, call talloc_free() on the + * event returned from this function. This event is automatically + * talloc_free()-ed after its event handler files, if it hasn't been freed yet. + * + * @note Unlike some mainloops, tevent timers are one-time events. To set up + * a recurring event, it is necessary to call tevent_add_timer() again during + * the handler processing. + * + * @note Due to the internal mainloop processing, a timer set to run + * immediately will do so after any other pending timers fire, but before + * any further file descriptor or signal handling events fire. Callers should + * not rely on this behavior! + */ +struct tevent_timer *tevent_add_timer(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + struct timeval next_event, + tevent_timer_handler_t handler, + void *private_data); +#else +struct tevent_timer *_tevent_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); +#define tevent_add_timer(ev, mem_ctx, next_event, handler, private_data) \ + _tevent_add_timer(ev, mem_ctx, next_event, handler, private_data, \ + #handler, __location__) +#endif + +/** + * @brief Set the time a tevent_timer fires + * + * @param[in] te The timer event to reset + * + * @param[in] next_event Timeval specifying the absolute time to fire this + * event. This is not an offset. + */ +void tevent_update_timer(struct tevent_timer *te, struct timeval next_event); + +/** + * @brief Associate a custom tag with the event. + * + * This tag can be then retrieved with tevent_timer_get_tag() + * + * @param[in] te The timer event. + * + * @param[in] tag Custom tag. + */ +void tevent_timer_set_tag(struct tevent_timer *te, uint64_t tag); + +/** + * @brief Get custom event tag. + */ +uint64_t tevent_timer_get_tag(const struct tevent_timer *te); + +#ifdef DOXYGEN +/** + * Initialize an immediate event object + * + * This object can be used to trigger an event to occur immediately after + * returning from the current event (before any other event occurs) + * + * @param[in] mem_ctx The talloc memory context to use as the parent + * + * @return An empty tevent_immediate object. Use tevent_schedule_immediate + * to populate and use it. + * + * @note Available as of tevent 0.9.8 + */ +struct tevent_immediate *tevent_create_immediate(TALLOC_CTX *mem_ctx); +#else +struct tevent_immediate *_tevent_create_immediate(TALLOC_CTX *mem_ctx, + const char *location); +#define tevent_create_immediate(mem_ctx) \ + _tevent_create_immediate(mem_ctx, __location__) +#endif + +#ifdef DOXYGEN + +/** + * Schedule an event for immediate execution. This event will occur + * immediately after returning from the current event (before any other + * event occurs) + * + * @param[in] im The tevent_immediate object to populate and use + * @param[in] ctx The tevent_context to run this event + * @param[in] handler The event handler to run when this event fires + * @param[in] private_data Data to pass to the event handler + */ +void tevent_schedule_immediate(struct tevent_immediate *im, + struct tevent_context *ctx, + tevent_immediate_handler_t handler, + void *private_data); +#else +void _tevent_schedule_immediate(struct tevent_immediate *im, + struct tevent_context *ctx, + tevent_immediate_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); +#define tevent_schedule_immediate(im, ctx, handler, private_data) \ + _tevent_schedule_immediate(im, ctx, handler, private_data, \ + #handler, __location__); +#endif + +/** + * @brief Associate a custom tag with the event. + * + * This tag can be then retrieved with tevent_immediate_get_tag() + * + * @param[in] im The immediate event. + * + * @param[in] tag Custom tag. + */ +void tevent_immediate_set_tag(struct tevent_immediate *im, uint64_t tag); + +/** + * @brief Get custom event tag. + */ +uint64_t tevent_immediate_get_tag(const struct tevent_immediate *fde); + +#ifdef DOXYGEN +/** + * @brief Add a tevent signal handler + * + * tevent_add_signal() creates a new event for handling a signal the next + * time through the mainloop. It implements a very simple traditional signal + * handler whose only purpose is to add the handler event into the mainloop. + * + * @param[in] ev The event context to work on. + * + * @param[in] mem_ctx The talloc memory context to use. + * + * @param[in] signum The signal to trap + * + * @param[in] handler The callback handler for the signal. + * + * @param[in] sa_flags sigaction flags for this signal handler. + * + * @param[in] private_data The private data passed to the callback handler. + * + * @return The newly-created signal handler event, or NULL on error. + * + * @note To cancel a signal handler, call talloc_free() on the event returned + * from this function. + * + * @see tevent_num_signals, tevent_sa_info_queue_count + */ +struct tevent_signal *tevent_add_signal(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + int signum, + int sa_flags, + tevent_signal_handler_t handler, + void *private_data); +#else +struct tevent_signal *_tevent_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); +#define tevent_add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data) \ + _tevent_add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data, \ + #handler, __location__) +#endif + +/** + * @brief Associate a custom tag with the event. + * + * This tag can be then retrieved with tevent_signal_get_tag() + * + * @param[in] fde The signal event. + * + * @param[in] tag Custom tag. + */ +void tevent_signal_set_tag(struct tevent_signal *se, uint64_t tag); + +/** + * @brief Get custom event tag. + */ +uint64_t tevent_signal_get_tag(const struct tevent_signal *se); + +/** + * @brief the number of supported signals + * + * This returns value of the configure time TEVENT_NUM_SIGNALS constant. + * + * The 'signum' argument of tevent_add_signal() must be less than + * TEVENT_NUM_SIGNALS. + * + * @see tevent_add_signal + */ +size_t tevent_num_signals(void); + +/** + * @brief the number of pending realtime signals + * + * This returns value of TEVENT_SA_INFO_QUEUE_COUNT. + * + * The tevent internals remember the last TEVENT_SA_INFO_QUEUE_COUNT + * siginfo_t structures for SA_SIGINFO signals. If the system generates + * more some signals get lost. + * + * @see tevent_add_signal + */ +size_t tevent_sa_info_queue_count(void); + +#ifdef DOXYGEN +/** + * @brief Pass a single time through the mainloop + * + * This will process any appropriate signal, immediate, fd and timer events + * + * @param[in] ev The event context to process + * + * @return Zero on success, nonzero if an internal error occurred + */ +int tevent_loop_once(struct tevent_context *ev); +#else +int _tevent_loop_once(struct tevent_context *ev, const char *location); +#define tevent_loop_once(ev) \ + _tevent_loop_once(ev, __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief Run the mainloop + * + * The mainloop will run until there are no events remaining to be processed + * + * @param[in] ev The event context to process + * + * @return Zero if all events have been processed. Nonzero if an internal + * error occurred. + */ +int tevent_loop_wait(struct tevent_context *ev); +#else +int _tevent_loop_wait(struct tevent_context *ev, const char *location); +#define tevent_loop_wait(ev) \ + _tevent_loop_wait(ev, __location__) +#endif + + +/** + * Assign a function to run when a tevent_fd is freed + * + * This function is a destructor for the tevent_fd. It does not automatically + * close the file descriptor. If this is the desired behavior, then it must be + * performed by the close_fn. + * + * @param[in] fde File descriptor event on which to set the destructor + * @param[in] close_fn Destructor to execute when fde is freed + * + * @note That the close_fn() on tevent_fd is *NOT* wrapped on contexts + * created by tevent_context_wrapper_create()! + * + * @see tevent_fd_set_close_fn + * @see tevent_context_wrapper_create + */ +void tevent_fd_set_close_fn(struct tevent_fd *fde, + tevent_fd_close_fn_t close_fn); + +/** + * Automatically close the file descriptor when the tevent_fd is freed + * + * This function calls close(fd) internally. + * + * @param[in] fde File descriptor event to auto-close + * + * @see tevent_fd_set_close_fn + */ +void tevent_fd_set_auto_close(struct tevent_fd *fde); + +/** + * Return the flags set on this file descriptor event + * + * @param[in] fde File descriptor event to query + * + * @return The flags set on the event. See #TEVENT_FD_READ and + * #TEVENT_FD_WRITE + */ +uint16_t tevent_fd_get_flags(struct tevent_fd *fde); + +/** + * Set flags on a file descriptor event + * + * @param[in] fde File descriptor event to set + * @param[in] flags Flags to set on the event. See #TEVENT_FD_READ and + * #TEVENT_FD_WRITE + */ +void tevent_fd_set_flags(struct tevent_fd *fde, uint16_t flags); + +/** + * Query whether tevent supports signal handling + * + * @param[in] ev An initialized tevent context + * + * @return True if this platform and tevent context support signal handling + */ +bool tevent_signal_support(struct tevent_context *ev); + +void tevent_set_abort_fn(void (*abort_fn)(const char *reason)); + +/* bits for file descriptor event flags */ + +/** + * Monitor a file descriptor for data to be read + */ +#define TEVENT_FD_READ 1 +/** + * Monitor a file descriptor for writeability + */ +#define TEVENT_FD_WRITE 2 + +/** + * Convenience function for declaring a tevent_fd writable + */ +#define TEVENT_FD_WRITEABLE(fde) \ + tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) | TEVENT_FD_WRITE) + +/** + * Convenience function for declaring a tevent_fd readable + */ +#define TEVENT_FD_READABLE(fde) \ + tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) | TEVENT_FD_READ) + +/** + * Convenience function for declaring a tevent_fd non-writable + */ +#define TEVENT_FD_NOT_WRITEABLE(fde) \ + tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) & ~TEVENT_FD_WRITE) + +/** + * Convenience function for declaring a tevent_fd non-readable + */ +#define TEVENT_FD_NOT_READABLE(fde) \ + tevent_fd_set_flags(fde, tevent_fd_get_flags(fde) & ~TEVENT_FD_READ) + +/** + * Debug level of tevent + */ +enum tevent_debug_level { + TEVENT_DEBUG_FATAL, + TEVENT_DEBUG_ERROR, + TEVENT_DEBUG_WARNING, + TEVENT_DEBUG_TRACE +}; + +/** + * @brief The tevent debug callbac. + * + * @param[in] context The memory context to use. + * + * @param[in] level The debug level. + * + * @param[in] fmt The format string. + * + * @param[in] ap The arguments for the format string. + */ +typedef void (*tevent_debug_fn)(void *context, + enum tevent_debug_level level, + const char *fmt, + va_list ap) PRINTF_ATTRIBUTE(3,0); + +/** + * Set destination for tevent debug messages + * + * @param[in] ev Event context to debug + * @param[in] debug Function to handle output printing + * @param[in] context The context to pass to the debug function. + * + * @return Always returns 0 as of version 0.9.8 + * + * @note Default is to emit no debug messages + */ +int tevent_set_debug(struct tevent_context *ev, + tevent_debug_fn debug, + void *context); + +/** + * Designate stderr for debug message output + * + * @param[in] ev Event context to debug + * + * @note This function will only output TEVENT_DEBUG_FATAL, TEVENT_DEBUG_ERROR + * and TEVENT_DEBUG_WARNING messages. For TEVENT_DEBUG_TRACE, please define a + * function for tevent_set_debug() + */ +int tevent_set_debug_stderr(struct tevent_context *ev); + +enum tevent_trace_point { + /** + * Corresponds to a trace point just before waiting + */ + TEVENT_TRACE_BEFORE_WAIT, + /** + * 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, + void *private_data); + +/** + * Register a callback to be called at certain trace points + * + * @param[in] ev Event context + * @param[in] cb Trace callback + * @param[in] private_data Data to be passed to callback + * + * @note The callback will be called at trace points defined by + * tevent_trace_point. Call with NULL to reset. + */ +void tevent_set_trace_callback(struct tevent_context *ev, + tevent_trace_callback_t cb, + void *private_data); + +/** + * Retrieve the current trace callback + * + * @param[in] ev Event context + * @param[out] cb Registered trace callback + * @param[out] private_data Registered data to be passed to callback + * + * @note This can be used to allow one component that wants to + * register a callback to respect the callback that another component + * has already registered. + */ +void tevent_get_trace_callback(struct tevent_context *ev, + tevent_trace_callback_t *cb, + void *private_data); + +enum tevent_event_trace_point { + /** + * Corresponds to a trace point just before the event is added. + */ + TEVENT_EVENT_TRACE_ATTACH, + + /** + * Corresponds to a trace point just before the event is removed. + */ + TEVENT_EVENT_TRACE_DETACH, + + /** + * Corresponds to a trace point just before the event handler is called. + */ + TEVENT_EVENT_TRACE_BEFORE_HANDLER, +}; + +typedef void (*tevent_trace_fd_callback_t)(struct tevent_fd *fde, + enum tevent_event_trace_point, + void *private_data); + +typedef void (*tevent_trace_signal_callback_t)(struct tevent_signal *se, + enum tevent_event_trace_point, + void *private_data); + +typedef void (*tevent_trace_timer_callback_t)(struct tevent_timer *te, + enum tevent_event_trace_point, + void *private_data); + +typedef void (*tevent_trace_immediate_callback_t)(struct tevent_immediate *im, + enum tevent_event_trace_point, + void *private_data); + +/** + * Register a callback to be called at certain trace points of fd event. + * + * @param[in] ev Event context + * @param[in] cb Trace callback + * @param[in] private_data Data to be passed to callback + * + * @note The callback will be called at trace points defined by + * tevent_event_trace_point. Call with NULL to reset. + */ +void tevent_set_trace_fd_callback(struct tevent_context *ev, + tevent_trace_fd_callback_t cb, + void *private_data); + +/** + * Retrieve the current trace callback of file descriptor event. + * + * @param[in] ev Event context + * @param[out] cb Registered trace callback + * @param[out] p_private_data Registered data to be passed to callback + * + * @note This can be used to allow one component that wants to + * register a callback to respect the callback that another component + * has already registered. + */ +void tevent_get_trace_fd_callback(struct tevent_context *ev, + tevent_trace_fd_callback_t *cb, + void *p_private_data); + +/** + * Register a callback to be called at certain trace points of signal event. + * + * @param[in] ev Event context + * @param[in] cb Trace callback + * @param[in] private_data Data to be passed to callback + * + * @note The callback will be called at trace points defined by + * tevent_event_trace_point. Call with NULL to reset. + */ +void tevent_set_trace_signal_callback(struct tevent_context *ev, + tevent_trace_signal_callback_t cb, + void *private_data); + +/** + * Retrieve the current trace callback of signal event. + * + * @param[in] ev Event context + * @param[out] cb Registered trace callback + * @param[out] p_private_data Registered data to be passed to callback + * + * @note This can be used to allow one component that wants to + * register a callback to respect the callback that another component + * has already registered. + */ +void tevent_get_trace_signal_callback(struct tevent_context *ev, + tevent_trace_signal_callback_t *cb, + void *p_private_data); + +/** + * Register a callback to be called at certain trace points of timer event. + * + * @param[in] ev Event context + * @param[in] cb Trace callback + * @param[in] private_data Data to be passed to callback + * + * @note The callback will be called at trace points defined by + * tevent_event_trace_point. Call with NULL to reset. + */ +void tevent_set_trace_timer_callback(struct tevent_context *ev, + tevent_trace_timer_callback_t cb, + void *private_data); + +/** + * Retrieve the current trace callback of timer event. + * + * @param[in] ev Event context + * @param[out] cb Registered trace callback + * @param[out] p_private_data Registered data to be passed to callback + * + * @note This can be used to allow one component that wants to + * register a callback to respect the callback that another component + * has already registered. + */ +void tevent_get_trace_timer_callback(struct tevent_context *ev, + tevent_trace_timer_callback_t *cb, + void *p_private_data); + +/** + * Register a callback to be called at certain trace points of immediate event. + * + * @param[in] ev Event context + * @param[in] cb Trace callback + * @param[in] private_data Data to be passed to callback + * + * @note The callback will be called at trace points defined by + * tevent_event_trace_point. Call with NULL to reset. + */ +void tevent_set_trace_immediate_callback(struct tevent_context *ev, + tevent_trace_immediate_callback_t cb, + void *private_data); + +/** + * Retrieve the current trace callback of immediate event. + * + * @param[in] ev Event context + * @param[out] cb Registered trace callback + * @param[out] p_private_data Registered data to be passed to callback + * + * @note This can be used to allow one component that wants to + * register a callback to respect the callback that another component + * has already registered. + */ +void tevent_get_trace_immediate_callback(struct tevent_context *ev, + tevent_trace_immediate_callback_t *cb, + void *p_private_data); + +/** + * @} + */ + +/** + * @defgroup tevent_request The tevent request functions. + * @ingroup tevent + * + * A tevent_req represents an asynchronous computation. + * + * The tevent_req group of API calls is the recommended way of + * programming async computations within tevent. In particular the + * file descriptor (tevent_add_fd) and timer (tevent_add_timed) events + * are considered too low-level to be used in larger computations. To + * read and write from and to sockets, Samba provides two calls on top + * of tevent_add_fd: tstream_read_packet_send/recv and tstream_writev_send/recv. + * These requests are much easier to compose than the low-level event + * handlers called from tevent_add_fd. + * + * A lot of the simplicity tevent_req has brought to the notoriously + * hairy async programming came via a set of conventions that every + * async computation programmed should follow. One central piece of + * these conventions is the naming of routines and variables. + * + * Every async computation needs a name (sensibly called "computation" + * down from here). From this name quite a few naming conventions are + * derived. + * + * Every computation that requires local state needs a + * @code + * struct computation_state { + * int local_var; + * }; + * @endcode + * Even if no local variables are required, such a state struct should + * be created containing a dummy variable. Quite a few helper + * functions and macros (for example tevent_req_create()) assume such + * a state struct. + * + * An async computation is started by a computation_send + * function. When it is finished, its result can be received by a + * computation_recv function. For an example how to set up an async + * computation, see the code example in the documentation for + * tevent_req_create() and tevent_req_post(). The prototypes for _send + * and _recv functions should follow some conventions: + * + * @code + * struct tevent_req *computation_send(TALLOC_CTX *mem_ctx, + * struct tevent_context *ev, + * ... further args); + * int computation_recv(struct tevent_req *req, ... further output args); + * @endcode + * + * The "int" result of computation_recv() depends on the result the + * sync version of the function would have, "int" is just an example + * here. + * + * Another important piece of the conventions is that the program flow + * is interrupted as little as possible. Because a blocking + * sub-computation requires that the flow needs to continue in a + * separate function that is the logical sequel of some computation, + * it should lexically follow sending off the blocking + * sub-computation. Setting the callback function via + * tevent_req_set_callback() requires referencing a function lexically + * below the call to tevent_req_set_callback(), forward declarations + * are required. A lot of the async computations thus begin with a + * sequence of declarations such as + * + * @code + * static void computation_step1_done(struct tevent_req *subreq); + * static void computation_step2_done(struct tevent_req *subreq); + * static void computation_step3_done(struct tevent_req *subreq); + * @endcode + * + * It really helps readability a lot to do these forward declarations, + * because the lexically sequential program flow makes the async + * computations almost as clear to read as a normal, sync program + * flow. + * + * It is up to the user of the async computation to talloc_free it + * after it has finished. If an async computation should be aborted, + * the tevent_req structure can be talloc_free'ed. After it has + * finished, it should talloc_free'ed by the API user. + * + * tevent_req variable naming conventions: + * + * The name of the variable pointing to the tevent_req structure + * returned by a _send() function SHOULD be named differently between + * implementation and caller. + * + * From the point of view of the implementation (of the _send() and + * _recv() functions) the variable returned by tevent_req_create() is + * always called @em req. + * + * While the caller of the _send() function should use @em subreq to + * hold the result. + * + * @see tevent_req_create() + * @see tevent_req_fn() + * + * @{ + */ + +/** + * An async request moves from TEVENT_REQ_INIT to + * TEVENT_REQ_IN_PROGRESS. All other states are valid after a request + * has finished. + */ +enum tevent_req_state { + /** + * We are creating the request + */ + TEVENT_REQ_INIT, + /** + * We are waiting the request to complete + */ + TEVENT_REQ_IN_PROGRESS, + /** + * The request is finished successfully + */ + TEVENT_REQ_DONE, + /** + * A user error has occurred. The user error has been + * indicated by tevent_req_error(), it can be retrieved via + * tevent_req_is_error(). + */ + TEVENT_REQ_USER_ERROR, + /** + * Request timed out after the timeout set by tevent_req_set_endtime. + */ + TEVENT_REQ_TIMED_OUT, + /** + * An internal allocation has failed, or tevent_req_nomem has + * been given a NULL pointer as the first argument. + */ + TEVENT_REQ_NO_MEMORY, + /** + * The request has been received by the caller. No further + * action is valid. + */ + TEVENT_REQ_RECEIVED +}; + +/** + * @brief An async request + */ +struct tevent_req; + +/** + * @brief A tevent request callback function. + * + * @param[in] subreq The tevent async request which executed this callback. + */ +typedef void (*tevent_req_fn)(struct tevent_req *subreq); + +/** + * @brief Set an async request callback. + * + * See the documentation of tevent_req_post() for an example how this + * is supposed to be used. + * + * @param[in] req The async request to set the callback. + * + * @param[in] fn The callback function to set. + * + * @param[in] pvt A pointer to private data to pass to the async request + * callback. + */ +void tevent_req_set_callback(struct tevent_req *req, tevent_req_fn fn, void *pvt); + +#ifdef DOXYGEN +/** + * @brief Get the private data cast to the given type for a callback from + * a tevent request structure. + * + * @code + * static void computation_done(struct tevent_req *subreq) { + * struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); + * struct computation_state *state = tevent_req_data(req, struct computation_state); + * .... more things, eventually maybe call tevent_req_done(req); + * } + * @endcode + * + * @param[in] req The structure to get the callback data from. + * + * @param[in] type The type of the private callback data to get. + * + * @return The type casted private data set NULL if not set. + */ +void *tevent_req_callback_data(struct tevent_req *req, #type); +#else +void *_tevent_req_callback_data(struct tevent_req *req); +#define tevent_req_callback_data(_req, _type) \ + talloc_get_type_abort(_tevent_req_callback_data(_req), _type) +#endif + +#ifdef DOXYGEN +/** + * @brief Get the private data for a callback from a tevent request structure. + * + * @param[in] req The structure to get the callback data from. + * + * @return The private data or NULL if not set. + */ +void *tevent_req_callback_data_void(struct tevent_req *req); +#else +#define tevent_req_callback_data_void(_req) \ + _tevent_req_callback_data(_req) +#endif + +#ifdef DOXYGEN +/** + * @brief Get the private data from a tevent request structure. + * + * When the tevent_req has been created by tevent_req_create, the + * result of tevent_req_data() is the state variable created by + * tevent_req_create() as a child of the req. + * + * @param[in] req The structure to get the private data from. + * + * @param[in] type The type of the private data + * + * @return The private data or NULL if not set. + */ +void *tevent_req_data(struct tevent_req *req, #type); +#else +void *_tevent_req_data(struct tevent_req *req); +#define tevent_req_data(_req, _type) \ + talloc_get_type_abort(_tevent_req_data(_req), _type) +#endif + +/** + * @brief The print function which can be set for a tevent async request. + * + * @param[in] req The tevent async request. + * + * @param[in] ctx A talloc memory context which can be uses to allocate + * memory. + * + * @return An allocated string buffer to print. + * + * Example: + * @code + * static char *my_print(struct tevent_req *req, TALLOC_CTX *mem_ctx) + * { + * struct my_data *data = tevent_req_data(req, struct my_data); + * char *result; + * + * result = tevent_req_default_print(mem_ctx, req); + * if (result == NULL) { + * return NULL; + * } + * + * return talloc_asprintf_append_buffer(result, "foo=%d, bar=%d", + * data->foo, data->bar); + * } + * @endcode + */ +typedef char *(*tevent_req_print_fn)(struct tevent_req *req, TALLOC_CTX *ctx); + +/** + * @brief This function sets a print function for the given request. + * + * This function can be used to setup a print function for the given request. + * This will be triggered if the tevent_req_print() function was + * called on the given request. + * + * @param[in] req The request to use. + * + * @param[in] fn A pointer to the print function + * + * @note This function should only be used for debugging. + */ +void tevent_req_set_print_fn(struct tevent_req *req, tevent_req_print_fn fn); + +/** + * @brief The default print function for creating debug messages. + * + * The function should not be used by users of the async API, + * but custom print function can use it and append custom text + * to the string. + * + * @param[in] req The request to be printed. + * + * @param[in] mem_ctx The memory context for the result. + * + * @return Text representation of request. + * + */ +char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx); + +/** + * @brief Print an tevent_req structure in debug messages. + * + * This function should be used by callers of the async API. + * + * @param[in] mem_ctx The memory context for the result. + * + * @param[in] req The request to be printed. + * + * @return Text representation of request. + */ +char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req); + +/** + * @brief A typedef for a cancel function for a tevent request. + * + * @param[in] req The tevent request calling this function. + * + * @return True if the request could be canceled, false if not. + */ +typedef bool (*tevent_req_cancel_fn)(struct tevent_req *req); + +/** + * @brief This function sets a cancel function for the given tevent request. + * + * This function can be used to setup a cancel function for the given request. + * This will be triggered if the tevent_req_cancel() function was + * called on the given request. + * + * @param[in] req The request to use. + * + * @param[in] fn A pointer to the cancel function. + */ +void tevent_req_set_cancel_fn(struct tevent_req *req, tevent_req_cancel_fn fn); + +#ifdef DOXYGEN +/** + * @brief Try to cancel the given tevent request. + * + * This function can be used to cancel the given request. + * + * It is only possible to cancel a request when the implementation + * has registered a cancel function via the tevent_req_set_cancel_fn(). + * + * @param[in] req The request to use. + * + * @return This function returns true if the request is + * cancelable, otherwise false is returned. + * + * @note Even if the function returns true, the caller need to wait + * for the function to complete normally. + * Only the _recv() function of the given request indicates + * if the request was really canceled. + */ +bool tevent_req_cancel(struct tevent_req *req); +#else +bool _tevent_req_cancel(struct tevent_req *req, const char *location); +#define tevent_req_cancel(req) \ + _tevent_req_cancel(req, __location__) +#endif + +/** + * @brief A typedef for a cleanup function for a tevent request. + * + * @param[in] req The tevent request calling this function. + * + * @param[in] req_state The current tevent_req_state. + * + */ +typedef void (*tevent_req_cleanup_fn)(struct tevent_req *req, + enum tevent_req_state req_state); + +/** + * @brief This function sets a cleanup function for the given tevent request. + * + * This function can be used to setup a cleanup function for the given request. + * This will be triggered when the tevent_req_done() or tevent_req_error() + * function was called, before notifying the callers callback function, + * and also before scheduling the deferred trigger. + * + * This might be useful if more than one tevent_req belong together + * and need to finish both requests at the same time. + * + * The cleanup function is able to call tevent_req_done() or tevent_req_error() + * recursively, the cleanup function is only triggered the first time. + * + * The cleanup function is also called by tevent_req_received() + * (possibly triggered from tevent_req_destructor()) before destroying + * the private data of the tevent_req. + * + * @param[in] req The request to use. + * + * @param[in] fn A pointer to the cancel function. + */ +void tevent_req_set_cleanup_fn(struct tevent_req *req, tevent_req_cleanup_fn fn); + +#ifdef DOXYGEN +/** + * @brief Create an async tevent request. + * + * The new async request will be initialized in state TEVENT_REQ_IN_PROGRESS. + * + * @code + * struct tevent_req *req; + * struct computation_state *state; + * req = tevent_req_create(mem_ctx, &state, struct computation_state); + * @endcode + * + * Tevent_req_create() allocates and zeros the state variable as a talloc + * child of its result. The state variable should be used as the talloc + * parent for all temporary variables that are allocated during the async + * computation. This way, when the user of the async computation frees + * the request, the state as a talloc child will be free'd along with + * all the temporary variables hanging off the state. + * + * @param[in] mem_ctx The memory context for the result. + * @param[in] pstate Pointer to the private request state. + * @param[in] type The name of the request. + * + * @return A new async request. NULL on error. + */ +struct tevent_req *tevent_req_create(TALLOC_CTX *mem_ctx, + void **pstate, #type); +#else +struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, + void *pstate, + size_t state_size, + const char *type, + const char *location); + +#define tevent_req_create(_mem_ctx, _pstate, _type) \ + _tevent_req_create((_mem_ctx), (_pstate), sizeof(_type), \ + #_type, __location__) +#endif + +/** + * @brief Set a timeout for an async request. On failure, "req" is already + * set to state TEVENT_REQ_NO_MEMORY. + * + * @param[in] req The request to set the timeout for. + * + * @param[in] ev The event context to use for the timer. + * + * @param[in] endtime The endtime of the request. + * + * @return True if succeeded, false if not. + */ +bool tevent_req_set_endtime(struct tevent_req *req, + struct tevent_context *ev, + struct timeval endtime); + +/** + * @brief Reset the timer set by tevent_req_set_endtime. + * + * @param[in] req The request to reset the timeout for + */ +void tevent_req_reset_endtime(struct tevent_req *req); + +#ifdef DOXYGEN +/** + * @brief Call the notify callback of the given tevent request manually. + * + * @param[in] req The tevent request to call the notify function from. + * + * @see tevent_req_set_callback() + */ +void tevent_req_notify_callback(struct tevent_req *req); +#else +void _tevent_req_notify_callback(struct tevent_req *req, const char *location); +#define tevent_req_notify_callback(req) \ + _tevent_req_notify_callback(req, __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief An async request has successfully finished. + * + * This function is to be used by implementors of async requests. When a + * request is successfully finished, this function calls the user's completion + * function. + * + * @param[in] req The finished request. + */ +void tevent_req_done(struct tevent_req *req); +#else +void _tevent_req_done(struct tevent_req *req, + const char *location); +#define tevent_req_done(req) \ + _tevent_req_done(req, __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief An async request has seen an error. + * + * This function is to be used by implementors of async requests. When a + * request can not successfully completed, the implementation should call this + * function with the appropriate status code. + * + * If error is 0 the function returns false and does nothing more. + * + * @param[in] req The request with an error. + * + * @param[in] error The error code. + * + * @return On success true is returned, false if error is 0. + * + * @code + * int error = first_function(); + * if (tevent_req_error(req, error)) { + * return; + * } + * + * error = second_function(); + * if (tevent_req_error(req, error)) { + * return; + * } + * + * tevent_req_done(req); + * return; + * @endcode + */ +bool tevent_req_error(struct tevent_req *req, + uint64_t error); +#else +bool _tevent_req_error(struct tevent_req *req, + uint64_t error, + const char *location); +#define tevent_req_error(req, error) \ + _tevent_req_error(req, error, __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief Helper function for nomem check. + * + * Convenience helper to easily check alloc failure within a callback + * implementing the next step of an async request. + * + * @param[in] p The pointer to be checked. + * + * @param[in] req The request being processed. + * + * @code + * p = talloc(mem_ctx, bla); + * if (tevent_req_nomem(p, req)) { + * return; + * } + * @endcode + */ +bool tevent_req_nomem(const void *p, + struct tevent_req *req); +#else +bool _tevent_req_nomem(const void *p, + struct tevent_req *req, + const char *location); +#define tevent_req_nomem(p, req) \ + _tevent_req_nomem(p, req, __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief Indicate out of memory to a request + * + * @param[in] req The request being processed. + */ +void tevent_req_oom(struct tevent_req *req); +#else +void _tevent_req_oom(struct tevent_req *req, + const char *location); +#define tevent_req_oom(req) \ + _tevent_req_oom(req, __location__) +#endif + +/** + * @brief Finish a request before the caller had a chance to set the callback. + * + * An implementation of an async request might find that it can either finish + * the request without waiting for an external event, or it can not even start + * the engine. To present the illusion of a callback to the user of the API, + * the implementation can call this helper function which triggers an + * immediate event. This way the caller can use the same calling + * conventions, independent of whether the request was actually deferred. + * + * @code + * struct tevent_req *computation_send(TALLOC_CTX *mem_ctx, + * struct tevent_context *ev) + * { + * struct tevent_req *req, *subreq; + * struct computation_state *state; + * req = tevent_req_create(mem_ctx, &state, struct computation_state); + * if (req == NULL) { + * return NULL; + * } + * subreq = subcomputation_send(state, ev); + * if (tevent_req_nomem(subreq, req)) { + * return tevent_req_post(req, ev); + * } + * tevent_req_set_callback(subreq, computation_done, req); + * return req; + * } + * @endcode + * + * @param[in] req The finished request. + * + * @param[in] ev The tevent_context for the immediate event. + * + * @return The given request will be returned. + */ +struct tevent_req *tevent_req_post(struct tevent_req *req, + struct tevent_context *ev); + +/** + * @brief Finish multiple requests within one function + * + * Normally tevent_req_notify_callback() and all wrappers + * (e.g. tevent_req_done() and tevent_req_error()) + * need to be the last thing an event handler should call. + * This is because the callback is likely to destroy the + * context of the current function. + * + * If a function wants to notify more than one caller, + * it is dangerous if it just triggers multiple callbacks + * in a row. With tevent_req_defer_callback() it is possible + * to set an event context that will be used to defer the callback + * via an immediate event (similar to tevent_req_post()). + * + * @code + * struct complete_state { + * struct tevent_context *ev; + * + * struct tevent_req **reqs; + * }; + * + * void complete(struct complete_state *state) + * { + * size_t i, c = talloc_array_length(state->reqs); + * + * for (i=0; i < c; i++) { + * tevent_req_defer_callback(state->reqs[i], state->ev); + * tevent_req_done(state->reqs[i]); + * } + * } + * @endcode + * + * @param[in] req The finished request. + * + * @param[in] ev The tevent_context for the immediate event. + * + * @return The given request will be returned. + */ +void tevent_req_defer_callback(struct tevent_req *req, + struct tevent_context *ev); + +/** + * @brief Check if the given request is still in progress. + * + * It is typically used by sync wrapper functions. + * + * @param[in] req The request to poll. + * + * @return The boolean form of "is in progress". + */ +bool tevent_req_is_in_progress(struct tevent_req *req); + +/** + * @brief Actively poll for the given request to finish. + * + * This function is typically used by sync wrapper functions. + * + * @param[in] req The request to poll. + * + * @param[in] ev The tevent_context to be used. + * + * @return On success true is returned. If a critical error has + * happened in the tevent loop layer false is returned. + * This is not the return value of the given request! + * + * @note This should only be used if the given tevent context was created by the + * caller, to avoid event loop nesting. + * + * @code + * req = tstream_writev_queue_send(mem_ctx, + * ev_ctx, + * tstream, + * send_queue, + * iov, 2); + * ok = tevent_req_poll(req, tctx->ev); + * rc = tstream_writev_queue_recv(req, &sys_errno); + * TALLOC_FREE(req); + * @endcode + */ +bool tevent_req_poll(struct tevent_req *req, + struct tevent_context *ev); + +/** + * @brief Get the tevent request state and the actual error set by + * tevent_req_error. + * + * @code + * int computation_recv(struct tevent_req *req, uint64_t *perr) + * { + * enum tevent_req_state state; + * uint64_t err; + * if (tevent_req_is_error(req, &state, &err)) { + * *perr = err; + * return -1; + * } + * return 0; + * } + * @endcode + * + * @param[in] req The tevent request to get the error from. + * + * @param[out] state A pointer to store the tevent request error state. + * + * @param[out] error A pointer to store the error set by tevent_req_error(). + * + * @return True if the function could set error and state, false + * otherwise. + * + * @see tevent_req_error() + */ +bool tevent_req_is_error(struct tevent_req *req, + enum tevent_req_state *state, + uint64_t *error); + +/** + * @brief Use as the last action of a _recv() function. + * + * This function destroys the attached private data. + * + * @param[in] req The finished request. + */ +void tevent_req_received(struct tevent_req *req); + +/** + * @brief Mark a tevent_req for profiling + * + * This will turn on profiling for this tevent_req an all subreqs that + * are directly started as helper requests off this + * tevent_req. subreqs are chained by walking up the talloc_parent + * hierarchy at a subreq's tevent_req_create. This means to get the + * profiling chain right the subreq that needs to be profiled as part + * of this tevent_req's profile must be a talloc child of the requests + * state variable. + * + * @param[in] req The request to do tracing for + * + * @return False if the profile could not be activated + */ +bool tevent_req_set_profile(struct tevent_req *req); + +struct tevent_req_profile; + +/** + * @brief Get the a request's profile for inspection + * + * @param[in] req The request to get the profile from + * + * @return The request's profile + */ +const struct tevent_req_profile *tevent_req_get_profile( + struct tevent_req *req); + +/** + * @brief Move the profile out of a request + * + * This function detaches the request's profile from the request, so + * that the profile can outlive the request in a _recv function. + * + * @param[in] req The request to move the profile out of + * @param[in] mem_ctx The new talloc context for the profile + * + * @return The moved profile + */ + +struct tevent_req_profile *tevent_req_move_profile(struct tevent_req *req, + TALLOC_CTX *mem_ctx); + +/** + * @brief Get a profile description + * + * @param[in] profile The profile to be queried + * @param[in] req_name The name of the request (state's name) + * + * "req_name" after this call is still in talloc-posession of "profile" + */ +void tevent_req_profile_get_name(const struct tevent_req_profile *profile, + const char **req_name); + +/** + * @brief Get a profile's start event data + * + * @param[in] profile The profile to be queried + * @param[in] start_location The location where this event started + * @param[in] start_time The time this event started + * + * "start_location" after this call is still in talloc-posession of "profile" + */ +void tevent_req_profile_get_start(const struct tevent_req_profile *profile, + const char **start_location, + struct timeval *start_time); + +/** + * @brief Get a profile's stop event data + * + * @param[in] profile The profile to be queried + * @param[in] stop_location The location where this event stopped + * @param[in] stop_time The time this event stopped + * + * "stop_location" after this call is still in talloc-posession of "profile" + */ +void tevent_req_profile_get_stop(const struct tevent_req_profile *profile, + const char **stop_location, + struct timeval *stop_time); + +/** + * @brief Get a profile's result data + * + * @param[in] pid The process where this profile was taken + * @param[in] state The status the profile's tevent_req finished with + * @param[in] user_error The user error of the profile's tevent_req + */ +void tevent_req_profile_get_status(const struct tevent_req_profile *profile, + pid_t *pid, + enum tevent_req_state *state, + uint64_t *user_error); + +/** + * @brief Retrieve the first subreq's profile from a profile + * + * @param[in] profile The profile to query + * + * @return The first tevent subreq's profile + */ +const struct tevent_req_profile *tevent_req_profile_get_subprofiles( + const struct tevent_req_profile *profile); + +/** + * @brief Walk the chain of subreqs + * + * @param[in] profile The subreq's profile to walk + * + * @return The next subprofile in the list + */ +const struct tevent_req_profile *tevent_req_profile_next( + const struct tevent_req_profile *profile); + +/** + * @brief Create a fresh tevent_req_profile + * + * @param[in] mem_ctx The talloc context to hang the fresh struct off + * + * @return The fresh struct + */ +struct tevent_req_profile *tevent_req_profile_create(TALLOC_CTX *mem_ctx); + +/** + * @brief Set a profile's name + * + * @param[in] profile The profile to set the name for + * @param[in] name The new name for the profile + * + * @return True if the internal talloc_strdup succeeded + */ +bool tevent_req_profile_set_name(struct tevent_req_profile *profile, + const char *name); + +/** + * @brief Set a profile's start event + * + * @param[in] profile The profile to set the start data for + * @param[in] start_location The new start location + * @param[in] start_time The new start time + * + * @return True if the internal talloc_strdup succeeded + */ +bool tevent_req_profile_set_start(struct tevent_req_profile *profile, + const char *start_location, + struct timeval start_time); + +/** + * @brief Set a profile's stop event + * + * @param[in] profile The profile to set the stop data for + * @param[in] stop_location The new stop location + * @param[in] stop_time The new stop time + * + * @return True if the internal talloc_strdup succeeded + */ +bool tevent_req_profile_set_stop(struct tevent_req_profile *profile, + const char *stop_location, + struct timeval stop_time); + +/** + * @brief Set a profile's exit status + * + * @param[in] profile The profile to set the exit status for + * @param[in] pid The process where this profile was taken + * @param[in] state The status the profile's tevent_req finished with + * @param[in] user_error The user error of the profile's tevent_req + */ +void tevent_req_profile_set_status(struct tevent_req_profile *profile, + pid_t pid, + enum tevent_req_state state, + uint64_t user_error); + +/** + * @brief Add a subprofile to a profile + * + * @param[in] parent_profile The profile to be modified + * @param[in] sub_profile The subreqs profile profile to be added + * + * "subreq" is talloc_move'ed into "parent_profile", so the talloc + * ownership of "sub_profile" changes + */ + +void tevent_req_profile_append_sub(struct tevent_req_profile *parent_profile, + struct tevent_req_profile **sub_profile); + +/** + * @brief Create a tevent subrequest at a given time. + * + * The idea is that always the same syntax for tevent requests. + * + * @param[in] mem_ctx The talloc memory context to use. + * + * @param[in] ev The event handle to setup the request. + * + * @param[in] wakeup_time The time to wakeup and execute the request. + * + * @return The new subrequest, NULL on error. + * + * Example: + * @code + * static void my_callback_wakeup_done(tevent_req *subreq) + * { + * struct tevent_req *req = tevent_req_callback_data(subreq, + * struct tevent_req); + * bool ok; + * + * ok = tevent_wakeup_recv(subreq); + * TALLOC_FREE(subreq); + * if (!ok) { + * tevent_req_error(req, -1); + * return; + * } + * ... + * } + * @endcode + * + * @code + * subreq = tevent_wakeup_send(mem_ctx, ev, wakeup_time); + * if (tevent_req_nomem(subreq, req)) { + * return false; + * } + * tevent_set_callback(subreq, my_callback_wakeup_done, req); + * @endcode + * + * @see tevent_wakeup_recv() + */ +struct tevent_req *tevent_wakeup_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct timeval wakeup_time); + +/** + * @brief Check if the wakeup has been correctly executed. + * + * This function needs to be called in the callback function set after calling + * tevent_wakeup_send(). + * + * @param[in] req The tevent request to check. + * + * @return True on success, false otherwise. + * + * @see tevent_wakeup_recv() + */ +bool tevent_wakeup_recv(struct tevent_req *req); + +/* @} */ + +/** + * @defgroup tevent_helpers The tevent helper functions + * @ingroup tevent + * + * @todo description + * + * @{ + */ + +/** + * @brief Compare two timeval values. + * + * @param[in] tv1 The first timeval value to compare. + * + * @param[in] tv2 The second timeval value to compare. + * + * @return 0 if they are equal. + * 1 if the first time is greater than the second. + * -1 if the first time is smaller than the second. + */ +int tevent_timeval_compare(const struct timeval *tv1, + const struct timeval *tv2); + +/** + * @brief Get a zero timeval value. + * + * @return A zero timeval value. + */ +struct timeval tevent_timeval_zero(void); + +/** + * @brief Get a timeval value for the current time. + * + * @return A timeval value with the current time. + */ +struct timeval tevent_timeval_current(void); + +/** + * @brief Get a timeval structure with the given values. + * + * @param[in] secs The seconds to set. + * + * @param[in] usecs The microseconds to set. + * + * @return A timeval structure with the given values. + */ +struct timeval tevent_timeval_set(uint32_t secs, uint32_t usecs); + +/** + * @brief Get the difference between two timeval values. + * + * @param[in] tv1 The first timeval. + * + * @param[in] tv2 The second timeval. + * + * @return A timeval structure with the difference between the + * first and the second value. + */ +struct timeval tevent_timeval_until(const struct timeval *tv1, + const struct timeval *tv2); + +/** + * @brief Check if a given timeval structure is zero. + * + * @param[in] tv The timeval to check if it is zero. + * + * @return True if it is zero, false otherwise. + */ +bool tevent_timeval_is_zero(const struct timeval *tv); + +/** + * @brief Add the given amount of time to a timeval structure. + * + * @param[in] tv The timeval structure to add the time. + * + * @param[in] secs The seconds to add to the timeval. + * + * @param[in] usecs The microseconds to add to the timeval. + * + * @return The timeval structure with the new time. + */ +struct timeval tevent_timeval_add(const struct timeval *tv, uint32_t secs, + uint32_t usecs); + +/** + * @brief Get a timeval in the future with a specified offset from now. + * + * @param[in] secs The seconds of the offset from now. + * + * @param[in] usecs The microseconds of the offset from now. + * + * @return A timeval with the given offset in the future. + */ +struct timeval tevent_timeval_current_ofs(uint32_t secs, uint32_t usecs); + +/** + * + * @brief A cached version of getpid() + * + * We use getpid() in a lot a performance critical situations + * in order to check if caches are still valid in the current process. + * + * Calling getpid() always add the cost of an additional syscall! + * + * When tevent is build with pthread support, we already make use + * of pthread_atfork(), so it's trivial to use it maintain a cache for getpid(). + * + * @return The pid of the current process. + */ +pid_t tevent_cached_getpid(void); + +/* @} */ + + +/** + * @defgroup tevent_queue The tevent queue functions + * @ingroup tevent + * + * A tevent_queue is used to queue up async requests that must be + * serialized. For example writing buffers into a socket must be + * serialized. Writing a large lump of data into a socket can require + * multiple write(2) or send(2) system calls. If more than one async + * request is outstanding to write large buffers into a socket, every + * request must individually be completed before the next one begins, + * even if multiple syscalls are required. + * + * Take a look at @ref tevent_queue_tutorial for more details. + * @{ + */ + +struct tevent_queue; +struct tevent_queue_entry; + +/** + * @brief Associate a custom tag with the queue entry. + * + * This tag can be then retrieved with tevent_queue_entry_get_tag() + * + * @param[in] qe The queue entry. + * + * @param[in] tag Custom tag. + */ +void tevent_queue_entry_set_tag(struct tevent_queue_entry *qe, uint64_t tag); + +/** + * @brief Get custom queue entry tag. + */ +uint64_t tevent_queue_entry_get_tag(const struct tevent_queue_entry *qe); + +typedef void (*tevent_trace_queue_callback_t)(struct tevent_queue_entry *qe, + enum tevent_event_trace_point, + void *private_data); + +/** + * Register a callback to be called at certain trace points of queue. + * + * @param[in] ev Event context + * @param[in] cb Trace callback + * @param[in] private_data Data to be passed to callback + * + * @note The callback will be called at trace points defined by + * tevent_event_trace_point. Call with NULL to reset. + */ +void tevent_set_trace_queue_callback(struct tevent_context *ev, + tevent_trace_queue_callback_t cb, + void *private_data); + +/** + * Retrieve the current trace callback of queue. + * + * @param[in] ev Event context + * @param[out] cb Registered trace callback + * @param[out] p_private_data Registered data to be passed to callback + * + * @note This can be used to allow one component that wants to + * register a callback to respect the callback that another component + * has already registered. + */ +void tevent_get_trace_queue_callback(struct tevent_context *ev, + tevent_trace_queue_callback_t *cb, + void *p_private_data); + +#ifdef DOXYGEN +/** + * @brief Create and start a tevent queue. + * + * @param[in] mem_ctx The talloc memory context to allocate the queue. + * + * @param[in] name The name to use to identify the queue. + * + * @return An allocated tevent queue on success, NULL on error. + * + * @see tevent_queue_start() + * @see tevent_queue_stop() + */ +struct tevent_queue *tevent_queue_create(TALLOC_CTX *mem_ctx, + const char *name); +#else +struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx, + const char *name, + const char *location); + +#define tevent_queue_create(_mem_ctx, _name) \ + _tevent_queue_create((_mem_ctx), (_name), __location__) +#endif + +/** + * @brief A callback trigger function run by the queue. + * + * @param[in] req The tevent request the trigger function is executed on. + * + * @param[in] private_data The private data pointer specified by + * tevent_queue_add(). + * + * @see tevent_queue_add() + * @see tevent_queue_add_entry() + * @see tevent_queue_add_optimize_empty() + */ +typedef void (*tevent_queue_trigger_fn_t)(struct tevent_req *req, + void *private_data); + +/** + * @brief Add a tevent request to the queue. + * + * @param[in] queue The queue to add the request. + * + * @param[in] ev The event handle to use for the request. + * + * @param[in] req The tevent request to add to the queue. + * + * @param[in] trigger The function triggered by the queue when the request + * is called. Since tevent 0.9.14 it's possible to + * pass NULL, in order to just add a "blocker" to the + * queue. + * + * @param[in] private_data The private data passed to the trigger function. + * + * @return True if the request has been successfully added, false + * otherwise. + */ +bool tevent_queue_add(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data); + +/** + * @brief Add a tevent request to the queue. + * + * The request can be removed from the queue by calling talloc_free() + * (or a similar function) on the returned queue entry. This + * is the only difference to tevent_queue_add(). + * + * @param[in] queue The queue to add the request. + * + * @param[in] ev The event handle to use for the request. + * + * @param[in] req The tevent request to add to the queue. + * + * @param[in] trigger The function triggered by the queue when the request + * is called. Since tevent 0.9.14 it's possible to + * pass NULL, in order to just add a "blocker" to the + * queue. + * + * @param[in] private_data The private data passed to the trigger function. + * + * @return a pointer to the tevent_queue_entry if the request + * has been successfully added, NULL otherwise. + * + * @see tevent_queue_add() + * @see tevent_queue_add_optimize_empty() + */ +struct tevent_queue_entry *tevent_queue_add_entry( + struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data); + +/** + * @brief Add a tevent request to the queue using a possible optimization. + * + * This tries to optimize for the empty queue case and may calls + * the trigger function directly. This is the only difference compared + * to tevent_queue_add_entry(). + * + * The caller needs to be prepared that the trigger function has + * already called tevent_req_notify_callback(), tevent_req_error(), + * tevent_req_done() or a similar function. + * + * The trigger function has no chance to see the returned + * queue_entry in the optimized case. + * + * The request can be removed from the queue by calling talloc_free() + * (or a similar function) on the returned queue entry. + * + * @param[in] queue The queue to add the request. + * + * @param[in] ev The event handle to use for the request. + * + * @param[in] req The tevent request to add to the queue. + * + * @param[in] trigger The function triggered by the queue when the request + * is called. Since tevent 0.9.14 it's possible to + * pass NULL, in order to just add a "blocker" to the + * queue. + * + * @param[in] private_data The private data passed to the trigger function. + * + * @return a pointer to the tevent_queue_entry if the request + * has been successfully added, NULL otherwise. + * + * @see tevent_queue_add() + * @see tevent_queue_add_entry() + */ +struct tevent_queue_entry *tevent_queue_add_optimize_empty( + struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data); + +/** + * @brief Untrigger an already triggered queue entry. + * + * If a trigger function detects that it needs to remain + * in the queue, it needs to call tevent_queue_stop() + * followed by tevent_queue_entry_untrigger(). + * + * @note In order to call tevent_queue_entry_untrigger() + * the queue must be already stopped and the given queue_entry + * must be the first one in the queue! Otherwise it calls abort(). + * + * @note You can't use this together with tevent_queue_add_optimize_empty() + * because the trigger function don't have access to the quene entry + * in the case of an empty queue. + * + * @param[in] queue_entry The queue entry to rearm. + * + * @see tevent_queue_add_entry() + * @see tevent_queue_stop() + */ +void tevent_queue_entry_untrigger(struct tevent_queue_entry *entry); + +/** + * @brief Start a tevent queue. + * + * The queue is started by default. + * + * @param[in] queue The queue to start. + */ +void tevent_queue_start(struct tevent_queue *queue); + +/** + * @brief Stop a tevent queue. + * + * The queue is started by default. + * + * @param[in] queue The queue to stop. + */ +void tevent_queue_stop(struct tevent_queue *queue); + +/** + * @brief Get the length of the queue. + * + * @param[in] queue The queue to get the length from. + * + * @return The number of elements. + */ +size_t tevent_queue_length(struct tevent_queue *queue); + +/** + * @brief Is the tevent queue running. + * + * The queue is started by default. + * + * @param[in] queue The queue. + * + * @return Whether the queue is running or not.. + */ +bool tevent_queue_running(struct tevent_queue *queue); + +/** + * @brief Create a tevent subrequest that waits in a tevent_queue + * + * The idea is that always the same syntax for tevent requests. + * + * @param[in] mem_ctx The talloc memory context to use. + * + * @param[in] ev The event handle to setup the request. + * + * @param[in] queue The queue to wait in. + * + * @return The new subrequest, NULL on error. + * + * @see tevent_queue_wait_recv() + */ +struct tevent_req *tevent_queue_wait_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct tevent_queue *queue); + +/** + * @brief Check if we no longer need to wait in the queue. + * + * This function needs to be called in the callback function set after calling + * tevent_queue_wait_send(). + * + * @param[in] req The tevent request to check. + * + * @return True on success, false otherwise. + * + * @see tevent_queue_wait_send() + */ +bool tevent_queue_wait_recv(struct tevent_req *req); + +typedef int (*tevent_nesting_hook)(struct tevent_context *ev, + void *private_data, + uint32_t level, + bool begin, + void *stack_ptr, + const char *location); + +/** + * @brief Create a tevent_thread_proxy for message passing between threads. + * + * The tevent_context must have been allocated on the NULL + * talloc context, and talloc_disable_null_tracking() must + * have been called. + * + * @param[in] dest_ev_ctx The tevent_context to receive events. + * + * @return An allocated tevent_thread_proxy, NULL on error. + * If tevent was compiled without PTHREAD support + * NULL is always returned and errno set to ENOSYS. + * + * @see tevent_thread_proxy_schedule() + */ +struct tevent_thread_proxy *tevent_thread_proxy_create( + struct tevent_context *dest_ev_ctx); + +/** + * @brief Schedule an immediate event on an event context from another thread. + * + * Causes dest_ev_ctx, being run by another thread, to receive an + * immediate event calling the handler with the *pp_private parameter. + * + * *pp_im must be a pointer to an immediate event talloced on a context owned + * by the calling thread, or the NULL context. Ownership will + * be transferred to the tevent_thread_proxy and *pp_im will be returned as NULL. + * + * *pp_private_data must be a talloced area of memory with no destructors. + * Ownership of this memory will be transferred to the tevent library and + * *pp_private_data will be set to NULL on successful completion of + * the call. Set pp_private to NULL if no parameter transfer + * needed (a pure callback). This is an asynchronous request, caller + * does not wait for callback to be completed before returning. + * + * @param[in] tp The tevent_thread_proxy to use. + * + * @param[in] pp_im Pointer to immediate event pointer. + * + * @param[in] handler The function that will be called. + * + * @param[in] pp_private_data The talloced memory to transfer. + * + * @see tevent_thread_proxy_create() + */ +void tevent_thread_proxy_schedule(struct tevent_thread_proxy *tp, + struct tevent_immediate **pp_im, + tevent_immediate_handler_t handler, + void *pp_private_data); + +/* + * @brief Create a context for threaded activation of immediates + * + * A tevent_treaded_context provides a link into an event + * context. Using tevent_threaded_schedule_immediate, it is possible + * to activate an immediate event from within a thread. + * + * It is the duty of the caller of tevent_threaded_context_create() to + * keep the event context around longer than any + * tevent_threaded_context. tevent will abort if ev is talloc_free'ed + * with an active tevent_threaded_context. + * + * If tevent is build without pthread support, this always returns + * NULL with errno=ENOSYS. + * + * @param[in] mem_ctx The talloc memory context to use. + * @param[in] ev The event context to link this to. + * @return The threaded context, or NULL with errno set. + * + * @see tevent_threaded_schedule_immediate() + * + * @note Available as of tevent 0.9.30 + */ +struct tevent_threaded_context *tevent_threaded_context_create( + TALLOC_CTX *mem_ctx, struct tevent_context *ev); + +#ifdef DOXYGEN +/* + * @brief Activate an immediate from a thread + * + * Activate an immediate from within a thread. + * + * This routine does not watch out for talloc hierarchies. This means + * that it is highly recommended to create the tevent_immediate in the + * thread owning tctx, allocate a threaded job description for the + * thread, hand over both pointers to a helper thread and not touch it + * in the main thread at all anymore. + * + * tevent_threaded_schedule_immediate is intended as a job completion + * indicator for simple threaded helpers. + * + * Please be aware that tevent_threaded_schedule_immediate is very + * picky about its arguments: An immediate may not already be + * activated and the handler must exist. With + * tevent_threaded_schedule_immediate memory ownership is transferred + * to the main thread holding the tevent context behind tctx, the + * helper thread can't access it anymore. + * + * @param[in] tctx The threaded context to go through + * @param[in] im The immediate event to activate + * @param[in] handler The immediate handler to call in the main thread + * @param[in] private_data Pointer for the immediate handler + * + * @see tevent_threaded_context_create() + * + * @note Available as of tevent 0.9.30 + */ +void tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx, + struct tevent_immediate *im, + tevent_immediate_handler_t handler, + void *private_data); +#else +void _tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx, + struct tevent_immediate *im, + tevent_immediate_handler_t handler, + void *private_data, + const char *handler_name, + const char *location); +#define tevent_threaded_schedule_immediate(tctx, im, handler, private_data) \ + _tevent_threaded_schedule_immediate(tctx, im, handler, private_data, \ + #handler, __location__); +#endif + +#ifdef TEVENT_DEPRECATED +#ifndef _DEPRECATED_ +#if __has_attribute(deprecated) || (__GNUC__ >= 3) +#define _DEPRECATED_ __attribute__ ((deprecated)) +#else +#define _DEPRECATED_ +#endif +#endif +void tevent_loop_allow_nesting(struct tevent_context *ev) _DEPRECATED_; +void tevent_loop_set_nesting_hook(struct tevent_context *ev, + tevent_nesting_hook hook, + void *private_data) _DEPRECATED_; +int _tevent_loop_until(struct tevent_context *ev, + bool (*finished)(void *private_data), + void *private_data, + const char *location) _DEPRECATED_; +#define tevent_loop_until(ev, finished, private_data) \ + _tevent_loop_until(ev, finished, private_data, __location__) +#endif + +int tevent_re_initialise(struct tevent_context *ev); + +/* @} */ + +/** + * @defgroup tevent_ops The tevent operation functions + * @ingroup tevent + * + * The following structure and registration functions are exclusively + * needed for people writing and pluggin a different event engine. + * There is nothing useful for normal tevent user in here. + * @{ + */ + +struct tevent_ops { + /* context init */ + int (*context_init)(struct tevent_context *ev); + + /* fd_event functions */ + struct tevent_fd *(*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); + void (*set_fd_close_fn)(struct tevent_fd *fde, + tevent_fd_close_fn_t close_fn); + uint16_t (*get_fd_flags)(struct tevent_fd *fde); + void (*set_fd_flags)(struct tevent_fd *fde, uint16_t flags); + + /* timed_event functions */ + struct tevent_timer *(*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); + + /* immediate event functions */ + void (*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); + + /* signal functions */ + struct tevent_signal *(*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); + + /* loop functions */ + int (*loop_once)(struct tevent_context *ev, const char *location); + int (*loop_wait)(struct tevent_context *ev, const char *location); +}; + +bool tevent_register_backend(const char *name, const struct tevent_ops *ops); + +/* @} */ + +#ifdef TEVENT_DEPRECATED +/** + * @defgroup tevent_wrapper_ops The tevent wrapper operation functions + * @ingroup tevent + * + * The following structure and registration functions are exclusively + * needed for people writing wrapper functions for event handlers + * e.g. wrappers can be used for debugging/profiling or impersonation. + * + * There is nothing useful for normal tevent user in here. + * + * @note That the close_fn() on tevent_fd is *NOT* wrapped! + * + * @see tevent_context_wrapper_create + * @see tevent_fd_set_auto_close + * @{ + */ + +struct tevent_wrapper_ops { + const char *name; + + bool (*before_use)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + const char *location); + void (*after_use)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + const char *location); + + void (*before_fd_handler)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + struct tevent_fd *fde, + uint16_t flags, + const char *handler_name, + const char *location); + void (*after_fd_handler)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + struct tevent_fd *fde, + uint16_t flags, + const char *handler_name, + const char *location); + + void (*before_timer_handler)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + struct tevent_timer *te, + struct timeval requested_time, + struct timeval trigger_time, + const char *handler_name, + const char *location); + void (*after_timer_handler)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + struct tevent_timer *te, + struct timeval requested_time, + struct timeval trigger_time, + const char *handler_name, + const char *location); + + void (*before_immediate_handler)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + struct tevent_immediate *im, + const char *handler_name, + const char *location); + void (*after_immediate_handler)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + struct tevent_immediate *im, + const char *handler_name, + const char *location); + + void (*before_signal_handler)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + const char *handler_name, + const char *location); + void (*after_signal_handler)(struct tevent_context *wrap_ev, + void *private_state, + struct tevent_context *main_ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + const char *handler_name, + const char *location); +}; + +#ifdef DOXYGEN +/** + * @brief Create a wrapper tevent_context. + * + * @param[in] main_ev The main event context to work on. + * + * @param[in] mem_ctx The talloc memory context to use. + * + * @param[in] ops The tevent_wrapper_ops function table. + * + * @param[out] private_state The private state use by the wrapper functions. + * + * @param[in] private_type The talloc type of the private_state. + * + * @return The wrapper event context, NULL on error. + * + * @note Available as of tevent 0.9.37 + * @note Deprecated as of tevent 0.9.38 + */ +struct tevent_context *tevent_context_wrapper_create(struct tevent_context *main_ev, + TALLOC_CTX *mem_ctx, + const struct tevent_wrapper_ops *ops, + void **private_state, + const char *private_type); +#else +struct tevent_context *_tevent_context_wrapper_create(struct tevent_context *main_ev, + TALLOC_CTX *mem_ctx, + const struct tevent_wrapper_ops *ops, + void *pstate, + size_t psize, + const char *type, + const char *location) _DEPRECATED_; +#define tevent_context_wrapper_create(main_ev, mem_ctx, ops, state, type) \ + _tevent_context_wrapper_create(main_ev, mem_ctx, ops, \ + state, sizeof(type), #type, __location__) +#endif + +/** + * @brief Check if the event context is a wrapper event context. + * + * @param[in] ev The event context to work on. + * + * @return Is a wrapper (true), otherwise (false). + * + * @see tevent_context_wrapper_create() + * + * @note Available as of tevent 0.9.37 + * @note Deprecated as of tevent 0.9.38 + */ +bool tevent_context_is_wrapper(struct tevent_context *ev) _DEPRECATED_; + +#ifdef DOXYGEN +/** + * @brief Prepare the environment of a (wrapper) event context. + * + * A caller might call this before passing a wrapper event context + * to a tevent_req based *_send() function. + * + * The wrapper event context might do something like impersonation. + * + * tevent_context_push_use() must always be used in combination + * with tevent_context_pop_use(). + * + * There is a global stack of currently active/busy wrapper event contexts. + * Each wrapper can only appear once on that global stack! + * The stack size is limited to 32 elements, which should be enough + * for all useful scenarios. + * + * In addition to an explicit tevent_context_push_use() also + * the invocation of an immediate, timer or fd handler implicitly + * pushes the wrapper on the stack. + * + * Therefore there are some strict constraints for the usage of + * tevent_context_push_use(): + * - It must not be called from within an event handler + * that already acts on the wrapper. + * - tevent_context_pop_use() must be called before + * leaving the code block that called tevent_context_push_use(). + * - The caller is responsible ensure the correct stack ordering + * - Any violation of these constraints results in calling + * the abort handler of the given tevent context. + * + * Calling tevent_context_push_use() on a raw event context + * still consumes an element on the stack, but it's otherwise + * a no-op. + * + * If tevent_context_push_use() returns false, it means + * that the wrapper's before_use() hook returned this failure, + * in that case you must not call tevent_context_pop_use() as + * the wrapper is not pushed onto the stack. + * + * @param[in] ev The event context to work on. + * + * @return Success (true) or failure (false). + * + * @note This is only needed if wrapper event contexts are in use. + * + * @see tevent_context_pop_use + * + * @note Available as of tevent 0.9.37 + * @note Deprecated as of tevent 0.9.38 + */ +bool tevent_context_push_use(struct tevent_context *ev); +#else +bool _tevent_context_push_use(struct tevent_context *ev, + const char *location) _DEPRECATED_; +#define tevent_context_push_use(ev) \ + _tevent_context_push_use(ev, __location__) +#endif + +#ifdef DOXYGEN +/** + * @brief Release the environment of a (wrapper) event context. + * + * The wrapper event context might undo something like impersonation. + * + * This must be called after a succesful tevent_context_push_use(). + * Any ordering violation results in calling + * the abort handler of the given tevent context. + * + * This basically calls the wrapper's after_use() hook. + * + * @param[in] ev The event context to work on. + * + * @note This is only needed if wrapper event contexts are in use. + * + * @see tevent_context_push_use + * + * @note Available as of tevent 0.9.37 + * @note Deprecated as of tevent 0.9.38 + */ +void tevent_context_pop_use(struct tevent_context *ev); +#else +void _tevent_context_pop_use(struct tevent_context *ev, + const char *location) _DEPRECATED_; +#define tevent_context_pop_use(ev) \ + _tevent_context_pop_use(ev, __location__) +#endif + +/** + * @brief Check is the two context pointers belong to the same low level loop + * + * With the introduction of wrapper contexts it's not trivial + * to check if two context pointers belong to the same low level + * event loop. Some code may need to know this in order + * to make some caching decisions. + * + * @param[in] ev1 The first event context. + * @param[in] ev2 The second event context. + * + * @return true if both contexts belong to the same (still existing) context + * loop, false otherwise. + * + * @see tevent_context_wrapper_create + * + * @note Available as of tevent 0.9.37 + * @note Deprecated as of tevent 0.9.38 + */ +bool tevent_context_same_loop(struct tevent_context *ev1, + struct tevent_context *ev2) _DEPRECATED_; + +/* @} */ +#endif /* TEVENT_DEPRECATED */ + +/** + * @defgroup tevent_compat The tevent compatibility functions + * @ingroup tevent + * + * The following definitions are usueful only for compatibility with the + * implementation originally developed within the samba4 code and will be + * soon removed. Please NEVER use in new code. + * + * @todo Ignore it? + * + * @{ + */ + +#ifdef TEVENT_COMPAT_DEFINES + +#define event_context tevent_context +#define event_ops tevent_ops +#define fd_event tevent_fd +#define timed_event tevent_timer +#define signal_event tevent_signal + +#define event_fd_handler_t tevent_fd_handler_t +#define event_timed_handler_t tevent_timer_handler_t +#define event_signal_handler_t tevent_signal_handler_t + +#define event_context_init(mem_ctx) \ + tevent_context_init(mem_ctx) + +#define event_context_init_byname(mem_ctx, name) \ + tevent_context_init_byname(mem_ctx, name) + +#define event_backend_list(mem_ctx) \ + tevent_backend_list(mem_ctx) + +#define event_set_default_backend(backend) \ + tevent_set_default_backend(backend) + +#define event_add_fd(ev, mem_ctx, fd, flags, handler, private_data) \ + tevent_add_fd(ev, mem_ctx, fd, flags, handler, private_data) + +#define event_add_timed(ev, mem_ctx, next_event, handler, private_data) \ + tevent_add_timer(ev, mem_ctx, next_event, handler, private_data) + +#define event_add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data) \ + tevent_add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data) + +#define event_loop_once(ev) \ + tevent_loop_once(ev) + +#define event_loop_wait(ev) \ + tevent_loop_wait(ev) + +#define event_get_fd_flags(fde) \ + tevent_fd_get_flags(fde) + +#define event_set_fd_flags(fde, flags) \ + tevent_fd_set_flags(fde, flags) + +#define EVENT_FD_READ TEVENT_FD_READ +#define EVENT_FD_WRITE TEVENT_FD_WRITE + +#define EVENT_FD_WRITEABLE(fde) \ + TEVENT_FD_WRITEABLE(fde) + +#define EVENT_FD_READABLE(fde) \ + TEVENT_FD_READABLE(fde) + +#define EVENT_FD_NOT_WRITEABLE(fde) \ + TEVENT_FD_NOT_WRITEABLE(fde) + +#define EVENT_FD_NOT_READABLE(fde) \ + TEVENT_FD_NOT_READABLE(fde) + +#define ev_debug_level tevent_debug_level + +#define EV_DEBUG_FATAL TEVENT_DEBUG_FATAL +#define EV_DEBUG_ERROR TEVENT_DEBUG_ERROR +#define EV_DEBUG_WARNING TEVENT_DEBUG_WARNING +#define EV_DEBUG_TRACE TEVENT_DEBUG_TRACE + +#define ev_set_debug(ev, debug, context) \ + tevent_set_debug(ev, debug, context) + +#define ev_set_debug_stderr(_ev) tevent_set_debug_stderr(ev) + +#endif /* TEVENT_COMPAT_DEFINES */ + +/* @} */ + +#endif /* __TEVENT_H__ */ diff --git a/lib/tevent/tevent.pc.in b/lib/tevent/tevent.pc.in new file mode 100644 index 0000000..eb0e564 --- /dev/null +++ b/lib/tevent/tevent.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: tevent +Description: An event system library +Version: @PACKAGE_VERSION@ +Requires: talloc +Libs: @LIB_RPATH@ -L${libdir} -ltevent +Cflags: -I${includedir} +URL: http://samba.org/ diff --git a/lib/tevent/tevent.py b/lib/tevent/tevent.py new file mode 100644 index 0000000..14aa27d --- /dev/null +++ b/lib/tevent/tevent.py @@ -0,0 +1,28 @@ +# +# 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, +) diff --git a/lib/tevent/tevent_debug.c b/lib/tevent/tevent_debug.c new file mode 100644 index 0000000..6b8f2d5 --- /dev/null +++ b/lib/tevent/tevent_debug.c @@ -0,0 +1,294 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 2005 + Copyright (C) Jelmer Vernooij 2005 + + ** 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 "replace.h" +#include "tevent.h" +#include "tevent_internal.h" + +/******************************************************************** + * Debug wrapper functions, modeled (with lot's of code copied as is) + * after the ev debug wrapper functions + ********************************************************************/ + +/* + this allows the user to choose their own debug function +*/ +int tevent_set_debug(struct tevent_context *ev, + void (*debug)(void *context, + enum tevent_debug_level level, + const char *fmt, + va_list ap) PRINTF_ATTRIBUTE(3,0), + void *context) +{ + if (ev->wrapper.glue != NULL) { + ev = tevent_wrapper_main_ev(ev); + tevent_abort(ev, "tevent_set_debug() on wrapper"); + errno = EINVAL; + return -1; + } + + ev->debug_ops.debug = debug; + ev->debug_ops.context = context; + return 0; +} + +/* + debug function for ev_set_debug_stderr +*/ +static void tevent_debug_stderr(void *private_data, + enum tevent_debug_level level, + const char *fmt, + va_list ap) PRINTF_ATTRIBUTE(3,0); +static void tevent_debug_stderr(void *private_data, + enum tevent_debug_level level, + const char *fmt, va_list ap) +{ + if (level <= TEVENT_DEBUG_WARNING) { + vfprintf(stderr, fmt, ap); + } +} + +/* + convenience function to setup debug messages on stderr + messages of level TEVENT_DEBUG_WARNING and higher are printed +*/ +int tevent_set_debug_stderr(struct tevent_context *ev) +{ + return tevent_set_debug(ev, tevent_debug_stderr, ev); +} + +/* + * log a message + * + * The default debug action is to ignore debugging messages. + * This is the most appropriate action for a library. + * Applications using the library must decide where to + * redirect debugging messages +*/ +void tevent_debug(struct tevent_context *ev, enum tevent_debug_level level, + const char *fmt, ...) +{ + va_list ap; + if (!ev) { + return; + } + if (ev->wrapper.glue != NULL) { + ev = tevent_wrapper_main_ev(ev); + } + if (ev->debug_ops.debug == NULL) { + return; + } + va_start(ap, fmt); + ev->debug_ops.debug(ev->debug_ops.context, level, fmt, ap); + va_end(ap); +} + +void tevent_set_trace_callback(struct tevent_context *ev, + tevent_trace_callback_t cb, + void *private_data) +{ + if (ev->wrapper.glue != NULL) { + ev = tevent_wrapper_main_ev(ev); + tevent_abort(ev, "tevent_set_trace_callback() on wrapper"); + return; + } + + ev->tracing.point.callback = cb; + ev->tracing.point.private_data = private_data; +} + +void tevent_get_trace_callback(struct tevent_context *ev, + tevent_trace_callback_t *cb, + void *private_data) +{ + *cb = ev->tracing.point.callback; + *(void**)private_data = ev->tracing.point.private_data; +} + +void tevent_trace_point_callback(struct tevent_context *ev, + enum tevent_trace_point tp) +{ + if (ev->tracing.point.callback != NULL) { + ev->tracing.point.callback(tp, ev->tracing.point.private_data); + } +} + +void tevent_set_trace_fd_callback(struct tevent_context *ev, + tevent_trace_fd_callback_t cb, + void *private_data) +{ + if (ev->wrapper.glue != NULL) { + ev = tevent_wrapper_main_ev(ev); + tevent_abort(ev, "tevent_set_trace_fd_callback() on wrapper"); + return; + } + + ev->tracing.fde.callback = cb; + ev->tracing.fde.private_data = private_data; +} + +void tevent_get_trace_fd_callback(struct tevent_context *ev, + tevent_trace_fd_callback_t *cb, + void *p_private_data) +{ + *cb = ev->tracing.fde.callback; + *(void**)p_private_data = ev->tracing.fde.private_data; +} + +void tevent_trace_fd_callback(struct tevent_context *ev, + struct tevent_fd *fde, + enum tevent_event_trace_point tp) +{ + if (ev->tracing.fde.callback != NULL) { + ev->tracing.fde.callback(fde, tp, ev->tracing.fde.private_data); + } +} + +void tevent_set_trace_signal_callback(struct tevent_context *ev, + tevent_trace_signal_callback_t cb, + void *private_data) +{ + if (ev->wrapper.glue != NULL) { + ev = tevent_wrapper_main_ev(ev); + tevent_abort(ev, "tevent_set_trace_signal_callback() " + "on wrapper"); + return; + } + + ev->tracing.se.callback = cb; + ev->tracing.se.private_data = private_data; +} + +void tevent_get_trace_signal_callback(struct tevent_context *ev, + tevent_trace_signal_callback_t *cb, + void *p_private_data) +{ + *cb = ev->tracing.se.callback; + *(void**)p_private_data = ev->tracing.se.private_data; +} + +void tevent_trace_signal_callback(struct tevent_context *ev, + struct tevent_signal *se, + enum tevent_event_trace_point tp) +{ + if (ev->tracing.se.callback != NULL) { + ev->tracing.se.callback(se, tp, ev->tracing.se.private_data); + } +} + +void tevent_set_trace_timer_callback(struct tevent_context *ev, + tevent_trace_timer_callback_t cb, + void *private_data) +{ + if (ev->wrapper.glue != NULL) { + ev = tevent_wrapper_main_ev(ev); + tevent_abort(ev, "tevent_set_trace_timer_callback() " + "on wrapper"); + return; + } + + ev->tracing.te.callback = cb; + ev->tracing.te.private_data = private_data; +} + +void tevent_get_trace_timer_callback(struct tevent_context *ev, + tevent_trace_timer_callback_t *cb, + void *p_private_data) +{ + *cb = ev->tracing.te.callback; + *(void**)p_private_data = ev->tracing.te.private_data; +} + +void tevent_trace_timer_callback(struct tevent_context *ev, + struct tevent_timer *te, + enum tevent_event_trace_point tp) +{ + if (ev->tracing.te.callback != NULL) { + ev->tracing.te.callback(te, tp, ev->tracing.te.private_data); + } +} + +void tevent_set_trace_immediate_callback(struct tevent_context *ev, + tevent_trace_immediate_callback_t cb, + void *private_data) +{ + if (ev->wrapper.glue != NULL) { + ev = tevent_wrapper_main_ev(ev); + tevent_abort(ev, "tevent_set_trace_immediate_callback() " + "on wrapper"); + return; + } + + ev->tracing.im.callback = cb; + ev->tracing.im.private_data = private_data; +} + +void tevent_get_trace_immediate_callback(struct tevent_context *ev, + tevent_trace_immediate_callback_t *cb, + void *p_private_data) +{ + *cb = ev->tracing.im.callback; + *(void**)p_private_data = ev->tracing.im.private_data; +} + +void tevent_trace_immediate_callback(struct tevent_context *ev, + struct tevent_immediate *im, + enum tevent_event_trace_point tp) +{ + if (ev->tracing.im.callback != NULL) { + ev->tracing.im.callback(im, tp, ev->tracing.im.private_data); + } +} + +void tevent_set_trace_queue_callback(struct tevent_context *ev, + tevent_trace_queue_callback_t cb, + void *private_data) +{ + if (ev->wrapper.glue != NULL) { + ev = tevent_wrapper_main_ev(ev); + tevent_abort(ev, "tevent_set_trace_queue_callback() " + "on wrapper"); + return; + } + + ev->tracing.qe.callback = cb; + ev->tracing.qe.private_data = private_data; +} + +void tevent_get_trace_queue_callback(struct tevent_context *ev, + tevent_trace_queue_callback_t *cb, + void *p_private_data) +{ + *cb = ev->tracing.qe.callback; + *(void**)p_private_data = ev->tracing.qe.private_data; +} + +void tevent_trace_queue_callback(struct tevent_context *ev, + struct tevent_queue_entry *qe, + enum tevent_event_trace_point tp) +{ + if (ev->tracing.qe.callback != NULL) { + ev->tracing.qe.callback(qe, tp, ev->tracing.qe.private_data); + } +} diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c new file mode 100644 index 0000000..1f1f47b --- /dev/null +++ b/lib/tevent/tevent_epoll.c @@ -0,0 +1,957 @@ +/* + Unix SMB/CIFS implementation. + + main select loop and event handling - epoll implementation + + Copyright (C) Andrew Tridgell 2003-2005 + 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 + ** 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 "replace.h" +#include "system/filesys.h" +#include "system/select.h" +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +struct epoll_event_context { + /* a pointer back to the generic event_context */ + struct tevent_context *ev; + + /* when using epoll this is the handle from epoll_create */ + 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_ void tevent_epoll_set_panic_fallback(struct tevent_context *ev, + bool (*panic_fallback)(struct tevent_context *ev, + bool replay)) +{ + struct epoll_event_context *epoll_ev = + talloc_get_type_abort(ev->additional_data, + struct epoll_event_context); + + epoll_ev->panic_fallback = panic_fallback; +} + +/* + called when a epoll call fails +*/ +static void epoll_panic(struct epoll_event_context *epoll_ev, + const char *reason, bool replay) +{ + 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(); + } +} + +/* + 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 epoll_event_context *epoll_ev) +{ + close(epoll_ev->epoll_fd); + epoll_ev->epoll_fd = -1; + return 0; +} + +/* + init the epoll fd +*/ +static int epoll_init_ctx(struct epoll_event_context *epoll_ev) +{ + epoll_ev->epoll_fd = epoll_create(64); + if (epoll_ev->epoll_fd == -1) { + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL, + "Failed to create epoll handle.\n"); + return -1; + } + + if (!ev_set_close_on_exec(epoll_ev->epoll_fd)) { + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_WARNING, + "Failed to set close-on-exec, file descriptor may be leaked to children.\n"); + } + + epoll_ev->pid = tevent_cached_getpid(); + talloc_set_destructor(epoll_ev, epoll_ctx_destructor); + + return 0; +} + +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 + 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; + pid_t pid = tevent_cached_getpid(); + + if (epoll_ev->pid == pid) { + return; + } + + close(epoll_ev->epoll_fd); + epoll_ev->epoll_fd = epoll_create(64); + if (epoll_ev->epoll_fd == -1) { + epoll_panic(epoll_ev, "epoll_create() failed", false); + return; + } + + if (!ev_set_close_on_exec(epoll_ev->epoll_fd)) { + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_WARNING, + "Failed to set close-on-exec, file descriptor may be leaked to children.\n"); + } + + epoll_ev->pid = pid; + epoll_ev->panic_state = &panic_triggered; + for (fde=epoll_ev->ev->fd_events;fde;fde=fde->next) { + 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; +} + +/* + 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->wrapper = NULL; + mpx_fde->event_ctx = NULL; + DLIST_REMOVE(epoll_ev->ev->fd_events, add_fde); + add_fde->wrapper = NULL; + 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 +*/ +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; + + 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; + 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->wrapper = NULL; + fde->event_ctx = NULL; + if (mpx_fde != NULL) { + DLIST_REMOVE(epoll_ev->ev->fd_events, mpx_fde); + mpx_fde->wrapper = NULL; + 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; + /* 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; + } +} + +/* + delete the epoll event for given fd_event +*/ +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; + + 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 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); + 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->wrapper = NULL; + fde->event_ctx = NULL; + if (mpx_fde != NULL) { + DLIST_REMOVE(epoll_ev->ev->fd_events, mpx_fde); + mpx_fde->wrapper = NULL; + mpx_fde->event_ctx = NULL; + } + return; + } else if (ret != 0) { + epoll_panic(epoll_ev, "EPOLL_CTL_DEL failed", false); + return; + } +} + +/* + change the epoll event to the given fd_event +*/ +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; + 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; + 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->wrapper = NULL; + fde->event_ctx = NULL; + if (mpx_fde != NULL) { + DLIST_REMOVE(epoll_ev->ev->fd_events, mpx_fde); + mpx_fde->wrapper = NULL; + 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_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 (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); + + 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) { + if (want_read || (want_write && !got_error)) { + 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. + * + * this is because epoll reports EPOLLERR and EPOLLHUP, even without asking for them + */ + epoll_del_event(epoll_ev, fde); + return; + } + + /* there's no epoll_event attached to the fde */ + if (want_read || (want_write && !got_error)) { + epoll_add_event(epoll_ev, fde); + return; + } +} + +/* + 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 +*/ +static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval *tvalp) +{ + int ret, i; +#define MAXEVENTS 1 + struct epoll_event events[MAXEVENTS]; + int timeout = -1; + int wait_errno; + + if (tvalp) { + /* it's better to trigger timed events a bit later than too early */ + timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000); + } + + if (epoll_ev->ev->signal_events && + tevent_common_check_signal(epoll_ev->ev)) { + return 0; + } + + 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 && wait_errno == EINTR && epoll_ev->ev->signal_events) { + if (tevent_common_check_signal(epoll_ev->ev)) { + return 0; + } + } + + if (ret == -1 && wait_errno != EINTR) { + epoll_panic(epoll_ev, "epoll_wait() failed", true); + return -1; + } + + if (ret == 0 && tvalp) { + /* we don't care about a possible delay here */ + tevent_common_loop_timer_delay(epoll_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; + struct tevent_fd *mpx_fde = NULL; + + if (fde == NULL) { + epoll_panic(epoll_ev, "epoll_wait() gave bad data", true); + return -1; + } + if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* + * Save off the multiplexed event in case we need + * to use it to call the handler function. + */ + 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) { + return tevent_common_invoke_fd_handler(fde, flags, NULL); + } + } + + return 0; +} + +/* + create a epoll_event_context structure. +*/ +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; + epoll_ev->epoll_fd = -1; + + ret = epoll_init_ctx(epoll_ev); + if (ret != 0) { + talloc_free(epoll_ev); + return ret; + } + + ev->additional_data = epoll_ev; + return 0; +} + +/* + destroy an fd_event +*/ +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 == 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); +} + +/* + add a fd based event + return NULL on failure (memory allocation error) +*/ +static struct tevent_fd *epoll_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 epoll_event_context *epoll_ev = + talloc_get_type_abort(ev->additional_data, + struct epoll_event_context); + struct tevent_fd *fde; + bool panic_triggered = false; + + fde = tevent_common_add_fd(ev, mem_ctx, fd, flags, + handler, private_data, + handler_name, location); + if (!fde) return NULL; + + talloc_set_destructor(fde, epoll_event_fd_destructor); + + 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; +} + +/* + set the fd event flags +*/ +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; + + ev = fde->event_ctx; + epoll_ev = talloc_get_type_abort(ev->additional_data, + struct epoll_event_context); + + fde->flags = flags; + + epoll_ev->panic_state = &panic_triggered; + epoll_check_reopen(epoll_ev); + if (panic_triggered) { + return; + } + epoll_ev->panic_state = NULL; + + epoll_update_event(epoll_ev, fde); +} + +/* + 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_abort(ev->additional_data, + struct epoll_event_context); + struct timeval tval; + bool panic_triggered = false; + + if (ev->signal_events && + tevent_common_check_signal(ev)) { + return 0; + } + + if (ev->threaded_contexts != NULL) { + tevent_common_threaded_activate_immediate(ev); + } + + 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_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); +} + +static const struct tevent_ops epoll_event_ops = { + .context_init = epoll_event_context_init, + .add_fd = epoll_event_add_fd, + .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_v2, + .schedule_immediate = tevent_common_schedule_immediate, + .add_signal = tevent_common_add_signal, + .loop_once = epoll_event_loop_once, + .loop_wait = tevent_common_loop_wait, +}; + +_PRIVATE_ bool tevent_epoll_init(void) +{ + return tevent_register_backend("epoll", &epoll_event_ops); +} diff --git a/lib/tevent/tevent_fd.c b/lib/tevent/tevent_fd.c new file mode 100644 index 0000000..0e55cf1 --- /dev/null +++ b/lib/tevent/tevent_fd.c @@ -0,0 +1,183 @@ +/* + Unix SMB/CIFS implementation. + + common events code for fd events + + Copyright (C) Stefan Metzmacher 2009 + + ** 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 "replace.h" +#define TEVENT_DEPRECATED 1 +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +int tevent_common_fd_destructor(struct tevent_fd *fde) +{ + if (fde->destroyed) { + tevent_common_check_double_free(fde, "tevent_fd double free"); + goto done; + } + fde->destroyed = true; + + if (fde->event_ctx) { + tevent_trace_fd_callback(fde->event_ctx, fde, TEVENT_EVENT_TRACE_DETACH); + DLIST_REMOVE(fde->event_ctx->fd_events, fde); + } + + if (fde->close_fn) { + fde->close_fn(fde->event_ctx, fde, fde->fd, fde->private_data); + fde->fd = -1; + fde->close_fn = NULL; + } + + fde->event_ctx = NULL; +done: + if (fde->busy) { + return -1; + } + fde->wrapper = NULL; + + return 0; +} + +struct tevent_fd *tevent_common_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 tevent_fd *fde; + + /* tevent will crash later on select() if we save + * a negative file descriptor. Better to fail here + * so that consumers will be able to debug it + */ + if (fd < 0) return NULL; + + fde = talloc(mem_ctx?mem_ctx:ev, struct tevent_fd); + if (!fde) return NULL; + + *fde = (struct tevent_fd) { + .event_ctx = ev, + .fd = fd, + .flags = flags, + .handler = handler, + .private_data = private_data, + .handler_name = handler_name, + .location = location, + }; + + tevent_trace_fd_callback(fde->event_ctx, fde, TEVENT_EVENT_TRACE_ATTACH); + DLIST_ADD(ev->fd_events, fde); + + talloc_set_destructor(fde, tevent_common_fd_destructor); + + + return fde; +} +uint16_t tevent_common_fd_get_flags(struct tevent_fd *fde) +{ + return fde->flags; +} + +void tevent_common_fd_set_flags(struct tevent_fd *fde, uint16_t flags) +{ + if (fde->flags == flags) return; + fde->flags = flags; +} + +void tevent_common_fd_set_close_fn(struct tevent_fd *fde, + tevent_fd_close_fn_t close_fn) +{ + fde->close_fn = close_fn; +} + +int tevent_common_invoke_fd_handler(struct tevent_fd *fde, uint16_t flags, + bool *removed) +{ + struct tevent_context *handler_ev = fde->event_ctx; + + if (removed != NULL) { + *removed = false; + } + + if (fde->event_ctx == NULL) { + return 0; + } + + fde->busy = true; + if (fde->wrapper != NULL) { + handler_ev = fde->wrapper->wrap_ev; + + tevent_wrapper_push_use_internal(handler_ev, fde->wrapper); + fde->wrapper->ops->before_fd_handler( + fde->wrapper->wrap_ev, + fde->wrapper->private_state, + fde->wrapper->main_ev, + fde, + flags, + fde->handler_name, + fde->location); + } + tevent_trace_fd_callback(fde->event_ctx, fde, TEVENT_EVENT_TRACE_BEFORE_HANDLER); + fde->handler(handler_ev, fde, flags, fde->private_data); + if (fde->wrapper != NULL) { + fde->wrapper->ops->after_fd_handler( + fde->wrapper->wrap_ev, + fde->wrapper->private_state, + fde->wrapper->main_ev, + fde, + flags, + fde->handler_name, + fde->location); + tevent_wrapper_pop_use_internal(handler_ev, fde->wrapper); + } + fde->busy = false; + + if (fde->destroyed) { + talloc_set_destructor(fde, NULL); + TALLOC_FREE(fde); + if (removed != NULL) { + *removed = true; + } + } + + return 0; +} + +void tevent_fd_set_tag(struct tevent_fd *fde, uint64_t tag) +{ + if (fde == NULL) { + return; + } + + fde->tag = tag; +} + +uint64_t tevent_fd_get_tag(const struct tevent_fd *fde) +{ + if (fde == NULL) { + return 0; + } + + return fde->tag; +} diff --git a/lib/tevent/tevent_immediate.c b/lib/tevent/tevent_immediate.c new file mode 100644 index 0000000..eb607c4 --- /dev/null +++ b/lib/tevent/tevent_immediate.c @@ -0,0 +1,261 @@ +/* + Unix SMB/CIFS implementation. + + common events code for immediate events + + Copyright (C) Stefan Metzmacher 2009 + + ** 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 "replace.h" +#define TEVENT_DEPRECATED 1 +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +static void tevent_common_immediate_cancel(struct tevent_immediate *im) +{ + const char *create_location = im->create_location; + bool busy = im->busy; + uint64_t tag = im->tag; + struct tevent_context *detach_ev_ctx = NULL; + + if (im->destroyed) { + tevent_abort(im->event_ctx, "tevent_immediate use after free"); + return; + } + + if (im->detach_ev_ctx != NULL) { + detach_ev_ctx = im->detach_ev_ctx; + im->detach_ev_ctx = NULL; + tevent_trace_immediate_callback(detach_ev_ctx, + im, + TEVENT_EVENT_TRACE_DETACH); + return; + } + + if (!im->event_ctx) { + return; + } + + if (im->handler_name != NULL) { + tevent_debug(im->event_ctx, TEVENT_DEBUG_TRACE, + "Cancel immediate event %p \"%s\"\n", + im, im->handler_name); + } + + /* let the backend free im->additional_data */ + if (im->cancel_fn) { + im->cancel_fn(im); + } + + if (busy && im->handler_name == NULL) { + detach_ev_ctx = im->event_ctx; + } else { + tevent_trace_immediate_callback(im->event_ctx, + im, + TEVENT_EVENT_TRACE_DETACH); + } + DLIST_REMOVE(im->event_ctx->immediate_events, im); + + *im = (struct tevent_immediate) { + .create_location = create_location, + .busy = busy, + .tag = tag, + .detach_ev_ctx = detach_ev_ctx, + }; + + if (!busy) { + talloc_set_destructor(im, NULL); + } +} + +/* + destroy an immediate event +*/ +static int tevent_common_immediate_destructor(struct tevent_immediate *im) +{ + if (im->destroyed) { + tevent_common_check_double_free(im, + "tevent_immediate double free"); + goto done; + } + + tevent_common_immediate_cancel(im); + + im->destroyed = true; + +done: + if (im->busy) { + return -1; + } + + return 0; +} + +/* + * schedule an immediate event on + */ +void tevent_common_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) +{ + const char *create_location = im->create_location; + bool busy = im->busy; + uint64_t tag = im->tag; + struct tevent_wrapper_glue *glue = im->wrapper; + + tevent_common_immediate_cancel(im); + + if (!handler) { + return; + } + + *im = (struct tevent_immediate) { + .event_ctx = ev, + .wrapper = glue, + .handler = handler, + .private_data = private_data, + .handler_name = handler_name, + .create_location = create_location, + .schedule_location = location, + .busy = busy, + .tag = tag, + }; + + tevent_trace_immediate_callback(im->event_ctx, im, TEVENT_EVENT_TRACE_ATTACH); + DLIST_ADD_END(ev->immediate_events, im); + talloc_set_destructor(im, tevent_common_immediate_destructor); + + tevent_debug(ev, TEVENT_DEBUG_TRACE, + "Schedule immediate event \"%s\": %p\n", + handler_name, im); +} + +int tevent_common_invoke_immediate_handler(struct tevent_immediate *im, + bool *removed) +{ + struct tevent_context *handler_ev = im->event_ctx; + struct tevent_context *ev = im->event_ctx; + struct tevent_immediate cur = *im; + + if (removed != NULL) { + *removed = false; + } + + tevent_debug(ev, TEVENT_DEBUG_TRACE, + "Run immediate event \"%s\": %p\n", + im->handler_name, im); + + /* + * remember the handler and then clear the event + * the handler might reschedule the event + */ + + im->busy = true; + im->handler_name = NULL; + tevent_common_immediate_cancel(im); + if (cur.wrapper != NULL) { + handler_ev = cur.wrapper->wrap_ev; + + tevent_wrapper_push_use_internal(handler_ev, cur.wrapper); + cur.wrapper->ops->before_immediate_handler( + cur.wrapper->wrap_ev, + cur.wrapper->private_state, + cur.wrapper->main_ev, + im, + cur.handler_name, + cur.schedule_location); + } + tevent_trace_immediate_callback(cur.event_ctx, im, TEVENT_EVENT_TRACE_BEFORE_HANDLER); + cur.handler(handler_ev, im, cur.private_data); + if (cur.wrapper != NULL) { + cur.wrapper->ops->after_immediate_handler( + cur.wrapper->wrap_ev, + cur.wrapper->private_state, + cur.wrapper->main_ev, + im, + cur.handler_name, + cur.schedule_location); + tevent_wrapper_pop_use_internal(handler_ev, cur.wrapper); + } + im->busy = false; + + /* The event was removed in tevent_common_immediate_cancel(). */ + if (im->detach_ev_ctx != NULL) { + struct tevent_context *detach_ev_ctx = im->detach_ev_ctx; + im->detach_ev_ctx = NULL; + tevent_trace_immediate_callback(detach_ev_ctx, + im, + TEVENT_EVENT_TRACE_DETACH); + } + + if (im->destroyed) { + talloc_set_destructor(im, NULL); + TALLOC_FREE(im); + if (removed != NULL) { + *removed = true; + } + } + + return 0; +} + +/* + trigger the first immediate event and return true + if no event was triggered return false +*/ +bool tevent_common_loop_immediate(struct tevent_context *ev) +{ + struct tevent_immediate *im = ev->immediate_events; + int ret; + + if (!im) { + return false; + } + + ret = tevent_common_invoke_immediate_handler(im, NULL); + if (ret != 0) { + tevent_abort(ev, "tevent_common_invoke_immediate_handler() failed"); + } + + return true; +} + + +void tevent_immediate_set_tag(struct tevent_immediate *im, uint64_t tag) +{ + if (im == NULL) { + return; + } + + im->tag = tag; +} + +uint64_t tevent_immediate_get_tag(const struct tevent_immediate *im) +{ + if (im == NULL) { + return 0; + } + + return im->tag; +} diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h new file mode 100644 index 0000000..3ca7fe1 --- /dev/null +++ b/lib/tevent/tevent_internal.h @@ -0,0 +1,527 @@ +/* + 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 + implementing new tevent backends. + + Copyright (C) Stefan Metzmacher 2005-2009 + + ** 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/>. +*/ + +struct tevent_req { + /** + * @brief What to do on completion + * + * This is used for the user of an async request, fn is called when + * the request completes, either successfully or with an error. + */ + struct { + /** + * @brief Completion function + * Completion function, to be filled by the API user + */ + tevent_req_fn fn; + /** + * @brief Private data for the completion function + */ + void *private_data; + } async; + + /** + * @brief Private state pointer for the actual implementation + * + * The implementation doing the work for the async request needs to + * keep around current data like for example a fd event. The user of + * an async request should not touch this. + */ + void *data; + + /** + * @brief A function to overwrite the default print function + * + * The implementation doing the work may want to implement a + * custom function to print the text representation of the async + * request. + */ + tevent_req_print_fn private_print; + + /** + * @brief A function to cancel the request + * + * The implementation might want to set a function + * that is called when the tevent_req_cancel() function + * was called. + */ + tevent_req_cancel_fn private_cancel; + + /** + * @brief A function to cleanup the request + * + * The implementation might want to set a function + * that is called before the tevent_req_done() and tevent_req_error() + * trigger the callers callback function. + */ + struct { + tevent_req_cleanup_fn fn; + enum tevent_req_state state; + } private_cleanup; + + /** + * @brief Internal state of the request + * + * Callers should only access this via functions and never directly. + */ + struct { + /** + * @brief The talloc type of the data pointer + * + * This is filled by the tevent_req_create() macro. + * + * This for debugging only. + */ + const char *private_type; + + /** + * @brief The location where the request was created + * + * This uses the __location__ macro via the tevent_req_create() + * macro. + * + * This for debugging only. + */ + const char *create_location; + + /** + * @brief The location where the request was finished + * + * This uses the __location__ macro via the tevent_req_done(), + * tevent_req_error() or tevent_req_nomem() macro. + * + * This for debugging only. + */ + const char *finish_location; + + /** + * @brief The location where the request was canceled + * + * This uses the __location__ macro via the + * tevent_req_cancel() macro. + * + * This for debugging only. + */ + const char *cancel_location; + + /** + * @brief The external state - will be queried by the caller + * + * While the async request is being processed, state will remain in + * TEVENT_REQ_IN_PROGRESS. A request is finished if + * req->state>=TEVENT_REQ_DONE. + */ + enum tevent_req_state state; + + /** + * @brief status code when finished + * + * This status can be queried in the async completion function. It + * will be set to 0 when everything went fine. + */ + uint64_t error; + + /** + * @brief the immediate event used by tevent_req_post + * + */ + struct tevent_immediate *trigger; + + /** + * @brief An event context which will be used to + * defer the _tevent_req_notify_callback(). + */ + struct tevent_context *defer_callback_ev; + + /** + * @brief the timer event if tevent_req_set_endtime was used + * + */ + struct tevent_timer *timer; + + /** + * @brief The place where profiling data is kept + */ + struct tevent_req_profile *profile; + } internal; +}; + +struct tevent_req_profile { + struct tevent_req_profile *prev, *next; + struct tevent_req_profile *parent; + const char *req_name; + pid_t pid; + const char *start_location; + struct timeval start_time; + const char *stop_location; + struct timeval stop_time; + enum tevent_req_state state; + uint64_t user_error; + struct tevent_req_profile *subprofiles; +}; + +struct tevent_fd { + struct tevent_fd *prev, *next; + struct tevent_context *event_ctx; + struct tevent_wrapper_glue *wrapper; + bool busy; + bool destroyed; + int fd; + uint16_t flags; /* see TEVENT_FD_* flags */ + tevent_fd_handler_t handler; + tevent_fd_close_fn_t close_fn; + /* this is private for the specific handler */ + void *private_data; + /* this is for debugging only! */ + const char *handler_name; + const char *location; + /* this is private for the events_ops implementation */ + uint64_t additional_flags; + void *additional_data; + /* custom tag that can be set by caller */ + uint64_t tag; +}; + +struct tevent_timer { + struct tevent_timer *prev, *next; + struct tevent_context *event_ctx; + struct tevent_wrapper_glue *wrapper; + bool busy; + bool destroyed; + struct timeval next_event; + tevent_timer_handler_t handler; + /* this is private for the specific handler */ + void *private_data; + /* this is for debugging only! */ + const char *handler_name; + const char *location; + /* this is private for the events_ops implementation */ + void *additional_data; + /* custom tag that can be set by caller */ + uint64_t tag; +}; + +struct tevent_immediate { + struct tevent_immediate *prev, *next; + struct tevent_context *event_ctx; + struct tevent_wrapper_glue *wrapper; + bool busy; + bool destroyed; + struct tevent_context *detach_ev_ctx; + tevent_immediate_handler_t handler; + /* this is private for the specific handler */ + void *private_data; + /* this is for debugging only! */ + const char *handler_name; + const char *create_location; + const char *schedule_location; + /* this is private for the events_ops implementation */ + void (*cancel_fn)(struct tevent_immediate *im); + void *additional_data; + /* custom tag that can be set by caller */ + uint64_t tag; +}; + +struct tevent_signal { + struct tevent_signal *prev, *next; + struct tevent_context *event_ctx; + struct tevent_wrapper_glue *wrapper; + bool busy; + bool destroyed; + int signum; + int sa_flags; + tevent_signal_handler_t handler; + /* this is private for the specific handler */ + void *private_data; + /* this is for debugging only! */ + const char *handler_name; + const char *location; + /* this is private for the events_ops implementation */ + void *additional_data; + /* custom tag that can be set by caller */ + uint64_t tag; +}; + +struct tevent_threaded_context { + struct tevent_threaded_context *next, *prev; + +#ifdef HAVE_PTHREAD + pthread_mutex_t event_ctx_mutex; +#endif + struct tevent_context *event_ctx; +}; + +struct tevent_debug_ops { + void (*debug)(void *context, enum tevent_debug_level level, + const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0); + void *context; +}; + +void tevent_debug(struct tevent_context *ev, enum tevent_debug_level level, + const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); + +void tevent_abort(struct tevent_context *ev, const char *reason); + +void tevent_common_check_double_free(TALLOC_CTX *ptr, const char *reason); + +struct tevent_context { + /* the specific events implementation */ + const struct tevent_ops *ops; + + /* + * The following three pointers are queried on every loop_once + * in the order in which they appear here. Not measured, but + * hopefully putting them at the top together with "ops" + * should make tevent a *bit* more cache-friendly than before. + */ + + /* list of signal events - used by common code */ + struct tevent_signal *signal_events; + + /* List of threaded job indicators */ + struct tevent_threaded_context *threaded_contexts; + + /* list of immediate events - used by common code */ + struct tevent_immediate *immediate_events; + + /* list of fd events - used by common code */ + struct tevent_fd *fd_events; + + /* list of timed events - used by common code */ + struct tevent_timer *timer_events; + + /* List of scheduled immediates */ + pthread_mutex_t scheduled_mutex; + struct tevent_immediate *scheduled_immediates; + + /* this is private for the events_ops implementation */ + void *additional_data; + + /* pipe hack used with signal handlers */ + struct tevent_fd *wakeup_fde; + int wakeup_fd; /* fd to write into */ +#ifndef HAVE_EVENT_FD + int wakeup_read_fd; +#endif + + /* debugging operations */ + struct tevent_debug_ops debug_ops; + + /* info about the nesting status */ + struct { + bool allowed; + uint32_t level; + tevent_nesting_hook hook_fn; + void *hook_private; + } nesting; + + struct { + struct { + tevent_trace_callback_t callback; + void *private_data; + } point; + + struct { + tevent_trace_fd_callback_t callback; + void *private_data; + } fde; + + struct { + tevent_trace_signal_callback_t callback; + void *private_data; + } se; + + struct { + tevent_trace_timer_callback_t callback; + void *private_data; + } te; + + struct { + tevent_trace_immediate_callback_t callback; + void *private_data; + } im; + + struct { + tevent_trace_queue_callback_t callback; + void *private_data; + } qe; + } tracing; + + struct { + /* + * This is used on the main event context + */ + struct tevent_wrapper_glue *list; + + /* + * This is used on the wrapper event context + */ + struct tevent_wrapper_glue *glue; + } wrapper; + + /* + * an optimization pointer into timer_events + * used by used by common code via + * tevent_common_add_timer_v2() + */ + struct tevent_timer *last_zero_timer; + +#ifdef HAVE_PTHREAD + struct tevent_context *prev, *next; +#endif +}; + +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, + const char *location); + +int tevent_common_fd_destructor(struct tevent_fd *fde); +struct tevent_fd *tevent_common_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); +void tevent_common_fd_set_close_fn(struct tevent_fd *fde, + tevent_fd_close_fn_t close_fn); +uint16_t tevent_common_fd_get_flags(struct tevent_fd *fde); +void tevent_common_fd_set_flags(struct tevent_fd *fde, uint16_t flags); +int tevent_common_invoke_fd_handler(struct tevent_fd *fde, uint16_t flags, + bool *removed); + +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); +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 *); +int tevent_common_invoke_timer_handler(struct tevent_timer *te, + struct timeval current_time, + bool *removed); + +void tevent_common_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); +int tevent_common_invoke_immediate_handler(struct tevent_immediate *im, + bool *removed); +bool tevent_common_loop_immediate(struct tevent_context *ev); +void tevent_common_threaded_activate_immediate(struct tevent_context *ev); + +bool tevent_common_have_events(struct tevent_context *ev); +int tevent_common_wakeup_init(struct tevent_context *ev); +int tevent_common_wakeup_fd(int fd); +int tevent_common_wakeup(struct tevent_context *ev); + +struct tevent_signal *tevent_common_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); +int tevent_common_check_signal(struct tevent_context *ev); +void tevent_cleanup_pending_signal_handlers(struct tevent_signal *se); +int tevent_common_invoke_signal_handler(struct tevent_signal *se, + int signum, int count, void *siginfo, + bool *removed); + +struct tevent_context *tevent_wrapper_main_ev(struct tevent_context *ev); + +struct tevent_wrapper_ops; + +struct tevent_wrapper_glue { + struct tevent_wrapper_glue *prev, *next; + struct tevent_context *wrap_ev; + struct tevent_context *main_ev; + bool busy; + bool destroyed; + const struct tevent_wrapper_ops *ops; + void *private_state; +}; + +void tevent_wrapper_push_use_internal(struct tevent_context *ev, + struct tevent_wrapper_glue *wrapper); +void tevent_wrapper_pop_use_internal(const struct tevent_context *__ev_ptr, + struct tevent_wrapper_glue *wrapper); + +bool tevent_standard_init(void); +bool tevent_poll_init(void); +bool 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); +void tevent_epoll_set_panic_fallback(struct tevent_context *ev, + bool (*panic_fallback)(struct tevent_context *ev, + bool replay)); +#endif +#ifdef HAVE_SOLARIS_PORTS +bool tevent_port_init(void); +#endif + + +void tevent_trace_point_callback(struct tevent_context *ev, + enum tevent_trace_point); + +void tevent_trace_fd_callback(struct tevent_context *ev, + struct tevent_fd *fde, + enum tevent_event_trace_point); + +void tevent_trace_signal_callback(struct tevent_context *ev, + struct tevent_signal *se, + enum tevent_event_trace_point); + +void tevent_trace_timer_callback(struct tevent_context *ev, + struct tevent_timer *te, + enum tevent_event_trace_point); + +void tevent_trace_immediate_callback(struct tevent_context *ev, + struct tevent_immediate *im, + enum tevent_event_trace_point); + +void tevent_trace_queue_callback(struct tevent_context *ev, + struct tevent_queue_entry *qe, + enum tevent_event_trace_point); diff --git a/lib/tevent/tevent_liboop.c b/lib/tevent/tevent_liboop.c new file mode 100644 index 0000000..68be76b --- /dev/null +++ b/lib/tevent/tevent_liboop.c @@ -0,0 +1,292 @@ +/* + Unix SMB/CIFS implementation. + main select loop and event handling + wrapper for http://git.lysator.liu.se/liboop/ + + Copyright (C) Stefan Metzmacher 2005 + + ** 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 "events.h" +#include "events_internal.h" + +#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) +{ + oop_source_sys *oop_sys = ev->additional_data; + + oop_sys_delete(oop_sys); + + return 0; +} + +/* + create a oop_event_context structure. +*/ +static int oop_event_context_init(struct tevent_context *ev, void *private_data) +{ + oop_source_sys *oop_sys = private_data; + + if (!oop_sys) { + oop_sys = oop_sys_new(); + if (!oop_sys) { + return -1; + } + + talloc_set_destructor(ev, oop_event_context_destructor); + } + + ev->additional_data = oop_sys; + + return 0; +} + +static void *oop_event_fd_handler(oop_source *oop, int fd, oop_event oop_type, void *ptr) +{ + struct tevent_fd *fde = ptr; + + if (fd != fde->fd) return OOP_ERROR; + + switch(oop_type) { + case OOP_READ: + fde->handler(fde->event_ctx, fde, EVENT_FD_READ, fde->private_data); + return OOP_CONTINUE; + case OOP_WRITE: + fde->handler(fde->event_ctx, fde, EVENT_FD_WRITE, fde->private_data); + return OOP_CONTINUE; + case OOP_EXCEPTION: + return OOP_ERROR; + case OOP_NUM_EVENTS: + return OOP_ERROR; + } + + return OOP_ERROR; +} + +/* + destroy an fd_event +*/ +static int oop_event_fd_destructor(struct tevent_fd *fde) +{ + struct tevent_context *ev = fde->event_ctx; + oop_source_sys *oop_sys = ev->additional_data; + oop_source *oop = oop_sys_source(oop_sys); + + if (fde->flags & EVENT_FD_READ) + oop->cancel_fd(oop, fde->fd, OOP_READ); + if (fde->flags & EVENT_FD_WRITE) + oop->cancel_fd(oop, fde->fd, OOP_WRITE); + + if (fde->flags & EVENT_FD_AUTOCLOSE) { + close(fde->fd); + fde->fd = -1; + } + + return 0; +} + +/* + add a fd based event + return NULL on failure (memory allocation error) +*/ +static struct tevent_fd *oop_event_add_fd(struct tevent_context *ev, TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, + event_fd_handler_t handler, + void *private_data) +{ + 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; + + fde->event_ctx = ev; + fde->fd = fd; + fde->flags = flags; + fde->handler = handler; + fde->private_data = private_data; + fde->additional_flags = 0; + fde->additional_data = NULL; + + if (fde->flags & EVENT_FD_READ) + oop->on_fd(oop, fde->fd, OOP_READ, oop_event_fd_handler, fde); + if (fde->flags & EVENT_FD_WRITE) + oop->on_fd(oop, fde->fd, OOP_WRITE, oop_event_fd_handler, fde); + + talloc_set_destructor(fde, oop_event_fd_destructor); + + return fde; +} + +/* + return the fd event flags +*/ +static uint16_t oop_event_get_fd_flags(struct tevent_fd *fde) +{ + return fde->flags; +} + +/* + set the fd event flags +*/ +static void oop_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags) +{ + oop_source_sys *oop_sys; + oop_source *oop; + + oop_sys = fde->event_ctx->additional_data; + oop = oop_sys_source(oop_sys); + + if ((fde->flags & EVENT_FD_READ)&&(!(flags & EVENT_FD_READ))) + oop->cancel_fd(oop, fde->fd, OOP_READ); + + if ((!(fde->flags & EVENT_FD_READ))&&(flags & EVENT_FD_READ)) + oop->on_fd(oop, fde->fd, OOP_READ, oop_event_fd_handler, fde); + + if ((fde->flags & EVENT_FD_WRITE)&&(!(flags & EVENT_FD_WRITE))) + oop->cancel_fd(oop, fde->fd, OOP_WRITE); + + if ((!(fde->flags & EVENT_FD_WRITE))&&(flags & EVENT_FD_WRITE)) + oop->on_fd(oop, fde->fd, OOP_WRITE, oop_event_fd_handler, fde); + + fde->flags = flags; +} + +static int oop_event_timed_destructor(struct tevent_timer *te); + +static int oop_event_timed_deny_destructor(struct tevent_timer *te) +{ + return -1; +} + +static void *oop_event_timed_handler(oop_source *oop, struct timeval t, void *ptr) +{ + struct tevent_timer *te = ptr; + + /* deny the handler to free the event */ + talloc_set_destructor(te, oop_event_timed_deny_destructor); + te->handler(te->event_ctx, te, t, te->private_data); + + talloc_set_destructor(te, oop_event_timed_destructor); + talloc_free(te); + + return OOP_CONTINUE; +} + +/* + destroy a timed event +*/ +static int oop_event_timed_destructor(struct tevent_timer *te) +{ + struct tevent_context *ev = te->event_ctx; + oop_source_sys *oop_sys = ev->additional_data; + oop_source *oop = oop_sys_source(oop_sys); + + oop->cancel_time(oop, te->next_event, oop_event_timed_handler, te); + + return 0; +} + +/* + add a timed event + 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) +{ + oop_source_sys *oop_sys = ev->additional_data; + oop_source *oop = oop_sys_source(oop_sys); + struct tevent_timer *te; + + te = talloc(mem_ctx?mem_ctx:ev, struct tevent_timer); + if (te == NULL) return NULL; + + te->event_ctx = ev; + te->next_event = next_event; + te->handler = handler; + te->private_data = private_data; + te->additional_data = NULL; + + oop->on_time(oop, te->next_event, oop_event_timed_handler, te); + + talloc_set_destructor(te, oop_event_timed_destructor); + + return te; +} + +/* + do a single event loop using the events defined in ev +*/ +static int oop_event_loop_once(struct tevent_context *ev) +{ + void *oop_ret; + oop_source_sys *oop_sys = ev->additional_data; + + oop_ret = oop_sys_run_once(oop_sys); + if (oop_ret == OOP_CONTINUE) { + return 0; + } + + return -1; +} + +/* + return on failure or (with 0) if all fd events are removed +*/ +static int oop_event_loop_wait(struct tevent_context *ev) +{ + void *oop_ret; + oop_source_sys *oop_sys = ev->additional_data; + + oop_ret = oop_sys_run(oop_sys); + if (oop_ret == OOP_CONTINUE) { + return 0; + } + + return -1; +} + +static const struct event_ops event_oop_ops = { + .context_init = oop_event_context_init, + .add_fd = oop_event_add_fd, + .get_fd_flags = oop_event_get_fd_flags, + .set_fd_flags = oop_event_set_fd_flags, + .add_timer = oop_event_add_timed, + .add_signal = common_event_add_signal, + .loop_once = oop_event_loop_once, + .loop_wait = oop_event_loop_wait, +}; + +const struct event_ops *event_liboop_get_ops(void) +{ + return &event_oop_ops; +} diff --git a/lib/tevent/tevent_poll.c b/lib/tevent/tevent_poll.c new file mode 100644 index 0000000..f4c6c2d --- /dev/null +++ b/lib/tevent/tevent_poll.c @@ -0,0 +1,663 @@ +/* + Unix SMB/CIFS implementation. + main select loop and event handling + Copyright (C) Andrew Tridgell 2003-2005 + Copyright (C) Stefan Metzmacher 2005-2009 + + ** 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 "replace.h" +#include "system/filesys.h" +#include "system/select.h" +#include "tevent.h" +#include "tevent_util.h" +#include "tevent_internal.h" + +struct poll_event_context { + /* a pointer back to the generic event_context */ + struct tevent_context *ev; + + /* + * one or more events were deleted or disabled + */ + bool deleted; + + /* + * These two arrays are maintained together. + * + * The following is always true: + * num_fds <= num_fdes + * + * new 'fresh' elements are added at the end + * of the 'fdes' array and picked up later + * to the 'fds' array in poll_event_sync_arrays() + * before the poll() syscall. + */ + struct pollfd *fds; + size_t num_fds; + struct tevent_fd **fdes; + size_t num_fdes; + + /* + * use tevent_common_wakeup(ev) to wake the poll() thread + */ + bool use_mt_mode; +}; + +/* + 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; + ev->additional_data = poll_ev; + return 0; +} + +static int poll_event_context_init_mt(struct tevent_context *ev) +{ + struct poll_event_context *poll_ev; + 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); + + ret = tevent_common_wakeup_init(ev); + if (ret != 0) { + return ret; + } + + poll_ev->use_mt_mode = true; + + return 0; +} + +static void poll_event_wake_pollthread(struct poll_event_context *poll_ev) +{ + if (!poll_ev->use_mt_mode) { + return; + } + tevent_common_wakeup(poll_ev->ev); +} + +/* + 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; + uint64_t del_idx = fde->additional_flags; + + if (ev == NULL) { + goto done; + } + + poll_ev = talloc_get_type_abort( + ev->additional_data, struct poll_event_context); + + if (del_idx == UINT64_MAX) { + 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_ bool 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); + uint64_t fde_idx = UINT64_MAX; + size_t num_fdes; + + fde->additional_flags = UINT64_MAX; + talloc_set_destructor(fde, poll_event_fd_destructor); + + if (fde->flags == 0) { + /* + * Nothing more to do... + */ + return true; + } + + /* + * We need to add it to the end of the 'fdes' array. + */ + num_fdes = poll_ev->num_fdes + 1; + if (num_fdes > talloc_array_length(poll_ev->fdes)) { + struct tevent_fd **tmp_fdes = NULL; + size_t array_length; + + array_length = (num_fdes + 15) & ~15; /* round up to 16 */ + + 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; + } + + fde_idx = poll_ev->num_fdes; + fde->additional_flags = fde_idx; + poll_ev->fdes[fde_idx] = fde; + poll_ev->num_fdes++; + + return true; +} + +/* + add a fd based event + return NULL on failure (memory allocation error) +*/ +static struct tevent_fd *poll_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 poll_event_context *poll_ev = talloc_get_type_abort( + ev->additional_data, struct poll_event_context); + struct tevent_fd *fde; + bool ok; + + if (fd < 0) { + return NULL; + } + + fde = tevent_common_add_fd(ev, + mem_ctx, + fd, + flags, + handler, + private_data, + handler_name, + location); + if (fde == NULL) { + return NULL; + } + + ok = tevent_poll_event_add_fd_internal(ev, fde); + if (!ok) { + TALLOC_FREE(fde); + return NULL; + } + poll_event_wake_pollthread(poll_ev); + + /* + * poll_event_loop_poll will take care of the rest in + * poll_event_setup_fresh + */ + return fde; +} + +/* + set the fd event flags +*/ +static void poll_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags) +{ + struct tevent_context *ev = fde->event_ctx; + struct poll_event_context *poll_ev; + uint64_t idx = fde->additional_flags; + uint16_t pollflags; + + if (ev == NULL) { + return; + } + + if (fde->flags == flags) { + return; + } + + poll_ev = talloc_get_type_abort( + ev->additional_data, struct poll_event_context); + + fde->flags = flags; + + if (idx == UINT64_MAX) { + /* + * We move it between the fresh and disabled lists. + */ + 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; + fde->additional_flags = UINT64_MAX; + poll_event_wake_pollthread(poll_ev); + return; + } + + if (idx >= poll_ev->num_fds) { + /* + * Not yet added to the + * poll_ev->fds array. + */ + poll_event_wake_pollthread(poll_ev); + return; + } + + pollflags = 0; + + if (flags & TEVENT_FD_READ) { + pollflags |= (POLLIN|POLLHUP); + } + if (flags & TEVENT_FD_WRITE) { + pollflags |= (POLLOUT); + } + poll_ev->fds[idx].events = pollflags; + + poll_event_wake_pollthread(poll_ev); +} + +static bool poll_event_sync_arrays(struct tevent_context *ev, + struct poll_event_context *poll_ev) +{ + size_t i; + size_t array_length; + + if (poll_ev->deleted) { + + for (i=0; i < poll_ev->num_fds;) { + struct tevent_fd *fde = poll_ev->fdes[i]; + size_t ci; + + if (fde != NULL) { + i++; + continue; + } + + /* + * This fde was talloc_free()'ed. Delete it + * from the arrays + */ + poll_ev->num_fds -= 1; + ci = poll_ev->num_fds; + if (ci > i) { + poll_ev->fds[i] = poll_ev->fds[ci]; + poll_ev->fdes[i] = poll_ev->fdes[ci]; + if (poll_ev->fdes[i] != NULL) { + poll_ev->fdes[i]->additional_flags = i; + } + } + poll_ev->fds[ci] = (struct pollfd) { .fd = -1 }; + poll_ev->fdes[ci] = NULL; + } + poll_ev->deleted = false; + } + + if (poll_ev->num_fds == poll_ev->num_fdes) { + return true; + } + + /* + * Recheck the size of both arrays and make sure + * poll_fd->fds array has at least the size of the + * in use poll_ev->fdes array. + */ + if (poll_ev->num_fdes > talloc_array_length(poll_ev->fds)) { + struct pollfd *tmp_fds = NULL; + + /* + * Make sure both allocated the same length. + */ + array_length = talloc_array_length(poll_ev->fdes); + + tmp_fds = talloc_realloc(poll_ev, + poll_ev->fds, + struct pollfd, + array_length); + if (tmp_fds == NULL) { + return false; + } + poll_ev->fds = tmp_fds; + } + + /* + * Now setup the new elements. + */ + for (i = poll_ev->num_fds; i < poll_ev->num_fdes; i++) { + struct tevent_fd *fde = poll_ev->fdes[i]; + struct pollfd *pfd = &poll_ev->fds[poll_ev->num_fds]; + + if (fde == NULL) { + continue; + } + + if (i > poll_ev->num_fds) { + poll_ev->fdes[poll_ev->num_fds] = fde; + fde->additional_flags = poll_ev->num_fds; + poll_ev->fdes[i] = NULL; + } + + 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); + } + + poll_ev->num_fds += 1; + } + /* Both are in sync again */ + poll_ev->num_fdes = poll_ev->num_fds; + + /* + * Check if we should shrink the arrays + * But keep at least 16 elements. + */ + + array_length = (poll_ev->num_fds + 15) & ~15; /* round up to 16 */ + array_length = MAX(array_length, 16); + if (array_length < talloc_array_length(poll_ev->fdes)) { + struct tevent_fd **tmp_fdes = NULL; + struct pollfd *tmp_fds = NULL; + + 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; + + tmp_fds = talloc_realloc(poll_ev, + poll_ev->fds, + struct pollfd, + array_length); + if (tmp_fds == NULL) { + return false; + } + poll_ev->fds = tmp_fds; + } + + return true; +} + +/* + event loop handling using poll() +*/ +static int poll_event_loop_poll(struct tevent_context *ev, + struct timeval *tvalp) +{ + struct poll_event_context *poll_ev = talloc_get_type_abort( + ev->additional_data, struct poll_event_context); + int pollrtn; + int timeout = -1; + int poll_errno; + struct tevent_fd *fde = NULL; + struct tevent_fd *next = NULL; + unsigned i; + bool ok; + + if (ev->signal_events && tevent_common_check_signal(ev)) { + return 0; + } + + if (tvalp != NULL) { + timeout = tvalp->tv_sec * 1000; + timeout += (tvalp->tv_usec + 999) / 1000; + } + + ok = poll_event_sync_arrays(ev, poll_ev); + if (!ok) { + 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) { + /* we don't care about a possible delay here */ + tevent_common_loop_timer_delay(ev); + return 0; + } + + if (pollrtn <= 0) { + /* + * No fd's ready + */ + return 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 = ev->fd_events; fde; fde = next) { + uint64_t idx = fde->additional_flags; + struct pollfd *pfd; + uint16_t flags = 0; + + next = fde->next; + + 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->wrapper = NULL; + fde->event_ctx = NULL; + continue; + } + + if (pfd->revents & (POLLHUP|POLLERR)) { + /* If we only wait for TEVENT_FD_WRITE, we + should not tell the event handler about it, + and remove the writable flag, as we only + report errors when waiting for read events + to match the select behavior. */ + if (!(fde->flags & TEVENT_FD_READ)) { + TEVENT_FD_NOT_WRITEABLE(fde); + continue; + } + flags |= TEVENT_FD_READ; + } + if (pfd->revents & POLLIN) { + flags |= TEVENT_FD_READ; + } + 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); + return tevent_common_invoke_fd_handler(fde, flags, NULL); + } + } + + 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->wrapper = NULL; + fde->event_ctx = NULL; + } + } + } + + return 0; +} + +/* + do a single event loop using the events defined in ev +*/ +static int poll_event_loop_once(struct tevent_context *ev, + const char *location) +{ + struct timeval tval; + + if (ev->signal_events && + tevent_common_check_signal(ev)) { + return 0; + } + + if (ev->threaded_contexts != NULL) { + tevent_common_threaded_activate_immediate(ev); + } + + 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; + } + + return poll_event_loop_poll(ev, &tval); +} + +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_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, +}; + +_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 = tevent_common_loop_wait, +}; + +_PRIVATE_ bool tevent_poll_mt_init(void) +{ + return tevent_register_backend("poll_mt", &poll_event_mt_ops); +} diff --git a/lib/tevent/tevent_port.c b/lib/tevent/tevent_port.c new file mode 100644 index 0000000..ccb65a7 --- /dev/null +++ b/lib/tevent/tevent_port.c @@ -0,0 +1,804 @@ +/* + Unix SMB/CIFS implementation. + + Main select loop and event handling - Solaris port implementation. + Losely based on the Linux epoll backend. + + 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 + ** 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 "replace.h" +#include "system/filesys.h" +#include "system/select.h" +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +struct port_associate_vals { + struct port_associate_vals *prev, *next; + struct port_event_context *port_ev; + int events; + struct tevent_fd *fde; + bool associated_event; +}; + +struct port_event_context { + /* a pointer back to the generic event_context */ + struct tevent_context *ev; + + /* This is the handle from port_create */ + int port_fd; + + pid_t pid; + + /* List of associations. */ + struct port_associate_vals *po_vals; +}; + +#define PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION (1<<0) +#define PORT_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1) +#define PORT_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2) +#define PORT_ADDITIONAL_FD_FLAG_HAS_MPX (1<<3) + +/* + Map from TEVENT_FD_* to POLLIN/POLLOUT +*/ +static int port_map_flags(uint16_t flags) +{ + int ret = 0; + if (flags & TEVENT_FD_READ) ret |= (POLLIN | POLLERR | POLLHUP); + if (flags & TEVENT_FD_WRITE) ret |= (POLLOUT | POLLERR | POLLHUP); + return ret; +} + +/* + Free the port fd +*/ +static int port_ctx_destructor(struct port_event_context *port_ev) +{ + close(port_ev->port_fd); + port_ev->port_fd = -1; + return 0; +} + +/* + Init the port fd +*/ +static int port_init_ctx(struct port_event_context *port_ev) +{ + port_ev->port_fd = port_create(); + if (port_ev->port_fd == -1) { + tevent_debug(port_ev->ev, TEVENT_DEBUG_FATAL, + "Failed to create port handle.\n"); + return -1; + } + + if (!ev_set_close_on_exec(port_ev->port_fd)) { + tevent_debug(port_ev->ev, TEVENT_DEBUG_WARNING, + "Failed to set close-on-exec, file descriptor may be leaked to children.\n"); + } + + port_ev->pid = tevent_cached_getpid(); + talloc_set_destructor(port_ev, port_ctx_destructor); + + return 0; +} + +/* + Functions to manage the lower level cache of associated events on the port_fd. +*/ + +static int port_associate_vals_destructor(struct port_associate_vals *val) +{ + DLIST_REMOVE(val->port_ev->po_vals, val); + memset(val, '\0', sizeof(struct port_associate_vals)); + return 0; +} + +/* + * TODO: As the port_association is per-fde, it should be possible to store it + * directly in fde->additional_data, alongside any multiplexed-fde. That way the + * lookup on store and delete would be avoided, and associate_all_events() could + * walk the ev->fd_events list. + */ +static bool store_port_association(struct port_event_context *port_ev, + struct tevent_fd *fde, + int events) +{ + struct port_associate_vals *val; + + for (val = port_ev->po_vals; val; val = val->next) { + if (val->fde->fd == fde->fd) { + /* Association already attached to fd. */ + if (val->events != events) { + val->events = events; + val->associated_event = false; + } + return true; + } + } + + val = talloc_zero(port_ev, struct port_associate_vals); + if (val == NULL) { + return false; + } + + val->port_ev = port_ev; + val->fde = fde; + val->events = events; + val->associated_event = false; + + DLIST_ADD(port_ev->po_vals, val); + talloc_set_destructor(val, port_associate_vals_destructor); + + return true; +} + +static void delete_port_association(struct port_event_context *port_ev, + struct tevent_fd *fde) +{ + struct port_associate_vals *val; + + for (val = port_ev->po_vals; val; val = val->next) { + if (val->fde == fde) { + if (val->associated_event) { + (void)port_dissociate(port_ev->port_fd, + PORT_SOURCE_FD, + fde->fd); + } + talloc_free(val); + return; + } + } +} + +static int associate_all_events(struct port_event_context *port_ev) +{ + struct port_associate_vals *val; + + for (val = port_ev->po_vals; val; val = val->next) { + int ret; + if (val->associated_event) { + continue; + } + ret = port_associate(port_ev->port_fd, + PORT_SOURCE_FD, + (uintptr_t)val->fde->fd, + val->events, + (void *)val); + if (ret != 0) { + return -1; + } + val->associated_event = true; + } + return 0; +} + +static int port_update_event(struct port_event_context *port_ev, struct tevent_fd *fde); + +/* + Reopen the port handle when our pid changes. + */ +static int port_check_reopen(struct port_event_context *port_ev) +{ + struct tevent_fd *fde; + pid_t pid = tevent_cached_getpid(); + + if (port_ev->pid == pid) { + return 0; + } + + close(port_ev->port_fd); + port_ev->port_fd = port_create(); + if (port_ev->port_fd == -1) { + tevent_debug(port_ev->ev, TEVENT_DEBUG_FATAL, + "port_create() failed"); + return -1; + } + + if (!ev_set_close_on_exec(port_ev->port_fd)) { + tevent_debug(port_ev->ev, TEVENT_DEBUG_WARNING, + "Failed to set close-on-exec, file descriptor may be leaked to children.\n"); + } + + port_ev->pid = pid; + for (fde=port_ev->ev->fd_events;fde;fde=fde->next) { + fde->additional_flags &= PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION; + if (port_update_event(port_ev, fde) != 0) { + return -1; + } + } + return 0; +} + +/* + * Solaris ports 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 void port_setup_multiplex_fd(struct port_event_context *port_ev, + struct tevent_fd *add_fde, + struct tevent_fd *mpx_fde) +{ + /* + * 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 = add_fde; + add_fde->additional_data = mpx_fde; + + /* Now flag both fde's as being multiplexed. */ + mpx_fde->additional_flags |= PORT_ADDITIONAL_FD_FLAG_HAS_MPX; + add_fde->additional_flags |= PORT_ADDITIONAL_FD_FLAG_HAS_MPX; + + /* We need to keep the GOT_ERROR flag. */ + if (mpx_fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_GOT_ERROR) { + add_fde->additional_flags |= PORT_ADDITIONAL_FD_FLAG_GOT_ERROR; + } +} + +/* + Add the port event to the given fd_event, + Or modify an existing event. +*/ + +static int port_add_event(struct port_event_context *port_ev, struct tevent_fd *fde) +{ + int flags = port_map_flags(fde->flags); + struct tevent_fd *mpx_fde = NULL; + + fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION; + fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_REPORT_ERROR; + + if (fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* + * This is already 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 &= ~PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION; + mpx_fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_REPORT_ERROR; + + flags |= port_map_flags(mpx_fde->flags); + } else { + /* + * Not (yet) a multiplexed event. See if there + * is already an event with the same fd. + */ + for (mpx_fde = port_ev->ev->fd_events; mpx_fde; mpx_fde = mpx_fde->next) { + if (mpx_fde->fd != fde->fd) { + continue; + } + if (mpx_fde == fde) { + continue; + } + /* Same fd. */ + break; + } + if (mpx_fde) { + if (mpx_fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* Logic error. Can't have more then 2 multiplexed fde's. */ + tevent_debug(port_ev->ev, TEVENT_DEBUG_FATAL, + "multiplex fde for fd[%d] is already multiplexed\n", + mpx_fde->fd); + return -1; + } + flags |= port_map_flags(mpx_fde->flags); + } + } + + if (!store_port_association(port_ev, + fde, + flags)) { + tevent_debug(port_ev->ev, TEVENT_DEBUG_FATAL, + "store_port_association failed for fd[%d]\n", + fde->fd); + return -1; + } + + /* Note we have an association now. */ + fde->additional_flags |= PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION; + /* Only if we want to read do we tell the event handler about errors. */ + if (fde->flags & TEVENT_FD_READ) { + fde->additional_flags |= PORT_ADDITIONAL_FD_FLAG_REPORT_ERROR; + } + if (mpx_fde == NULL) { + return 0; + } + /* Set up the multiplex pointer. Does no harm if already multiplexed. */ + port_setup_multiplex_fd(port_ev, + fde, + mpx_fde); + + mpx_fde->additional_flags |= PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION; + /* Only if we want to read do we tell the event handler about errors. */ + if (mpx_fde->flags & TEVENT_FD_READ) { + mpx_fde->additional_flags |= PORT_ADDITIONAL_FD_FLAG_REPORT_ERROR; + } + + return 0; +} + +/* + Delete the port association for the given fd_event. +*/ + +static void port_del_event(struct port_event_context *port_ev, struct tevent_fd *fde) +{ + struct tevent_fd *mpx_fde = NULL; + + fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION; + fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_REPORT_ERROR; + + if (fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* + * This is a multiplexed fde, we need to remove + * both associations. + */ + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + + mpx_fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION; + mpx_fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_REPORT_ERROR; + mpx_fde->additional_data = NULL; + + fde->additional_data = NULL; + } + delete_port_association(port_ev, fde); +} + +/* + Add or remove the port event from the given fd_event +*/ +static int port_update_event(struct port_event_context *port_ev, struct tevent_fd *fde) +{ + bool got_error = (fde->additional_flags & PORT_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 (fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* + * work out what the multiplexed fde wants. + */ + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + if (mpx_fde->flags & TEVENT_FD_READ) { + want_read = true; + } + if (mpx_fde->flags & TEVENT_FD_WRITE) { + want_write = true; + } + } + + if (fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION) { + /* There's already an association. */ + if (want_read || (want_write && !got_error)) { + return port_add_event(port_ev, fde); + } + /* + * If we want to match the select behavior, we need to remove the port event + * when the caller isn't interested in events. + */ + port_del_event(port_ev, fde); + return 0; + } + + /* There's no port event attached to the fde. */ + if (want_read || (want_write && !got_error)) { + return port_add_event(port_ev, fde); + } + return 0; +} + +/* + Cope with port_get returning EPOLLHP|EPOLLERR on an association. + Return true if there's nothing else to do, false if this event + needs further handling. +*/ + +static bool port_handle_hup_or_err(struct port_event_context *port_ev, + struct tevent_fd *fde) +{ + if (fde == NULL) { + return true; + } + + fde->additional_flags |= PORT_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 port association, + * as we only report error when waiting for read events, + * to match the select() behavior. + */ + if (!(fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_REPORT_ERROR)) { + /* + * Do the same as the poll backend and + * remove the writable flag. + */ + fde->flags &= ~TEVENT_FD_WRITE; + return true; + } + /* This has TEVENT_FD_READ set, we're not finished. */ + return false; +} + +/* + Event loop handling using Solaris ports. +*/ +static int port_event_loop(struct port_event_context *port_ev, struct timeval *tvalp) +{ + int ret; +#define MAXEVENTS 1 + port_event_t events[MAXEVENTS]; + uint_t nget = 1; + uint_t max_events = MAXEVENTS; + uint_t i; + int port_errno; + struct timespec ts; + struct tevent_context *ev = port_ev->ev; + + if (tvalp) { + ts.tv_sec = tvalp->tv_sec; + ts.tv_nsec = tvalp->tv_usec * 1000; + } + + if (port_ev->ev->signal_events && + tevent_common_check_signal(ev)) { + return 0; + } + + /* + * Solaris triggers sending the event to the port + * at the time the port association is done. Postpone + * associating fd's until just before we get the events, + * otherwise we can deadlock. + */ + + if (associate_all_events(port_ev) != 0) { + return -1; + } + + tevent_trace_point_callback(ev, TEVENT_TRACE_BEFORE_WAIT); + ret = port_getn(port_ev->port_fd, events, max_events, &nget, &ts); + port_errno = errno; + tevent_trace_point_callback(ev, TEVENT_TRACE_AFTER_WAIT); + + if (ret == -1 && port_errno == EINTR) { + if (ev->signal_events) { + tevent_common_check_signal(ev); + } + /* + * If no signal handlers we got an unsolicited + * signal wakeup. This can happen with epoll + * too. Just return and ignore. + */ + return 0; + } + + if (ret == -1 && port_errno == ETIME) { + /* + * If errno is set to ETIME it is possible that we still got an event. + * In that case we need to go through the processing loop so that we + * reassociate the received event with the port or the association will + * be lost so check the value of nget is 0 before returning. + */ + if (nget == 0) { + /* we don't care about a possible delay here */ + tevent_common_loop_timer_delay(ev); + return 0; + } + /* + * Set the return value to 0 since we do not actually have an error and we + * do have events that need to be processed. This keeps us from getting + * caught in the generic error test. + */ + ret = 0; + } + + if (ret == -1) { + tevent_debug(ev, TEVENT_DEBUG_ERROR, + "port_get failed (%s)\n", + strerror(errno)); + return -1; + } + + for (i = 0; i < nget; i++) { + struct tevent_fd *mpx_fde = NULL; + struct tevent_fd *fde = NULL; + uint16_t flags = 0; + struct port_associate_vals *val = talloc_get_type(events[i].portev_user, + struct port_associate_vals); + if (val == NULL) { + tevent_debug(ev, TEVENT_DEBUG_ERROR, + "port_getn() gave bad data"); + return -1; + } + + /* Mark this event as needing to be re-associated. */ + val->associated_event = false; + + fde = val->fde; + + if (fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* + * Save off the multiplexed event in case we need + * to use it to call the handler function. + */ + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + } + + if (events[i].portev_events & (POLLHUP|POLLERR)) { + bool handled_fde = port_handle_hup_or_err(port_ev, fde); + bool handled_mpx = port_handle_hup_or_err(port_ev, mpx_fde); + + if (handled_fde && handled_mpx) { + return port_update_event(port_ev, fde); + } + + 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].portev_events & POLLIN) { + flags |= TEVENT_FD_READ; + } + if (events[i].portev_events & POLLOUT) { + 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) { + return tevent_common_invoke_fd_handler(fde, flags, NULL); + } + } + + return 0; +} + + +/* + create a port_event_context structure. +*/ +static int port_event_context_init(struct tevent_context *ev) +{ + int ret; + struct port_event_context *port_ev; + + /* + * We might be called during tevent_re_initialise() + * which means we need to free our old additional_data. + */ + TALLOC_FREE(ev->additional_data); + + port_ev = talloc_zero(ev, struct port_event_context); + if (!port_ev) { + return -1; + } + port_ev->ev = ev; + port_ev->port_fd = -1; + port_ev->pid = (pid_t)-1; + + ret = port_init_ctx(port_ev); + if (ret != 0) { + talloc_free(port_ev); + return ret; + } + + ev->additional_data = port_ev; + return 0; +} + +/* + destroy an fd_event +*/ +static int port_event_fd_destructor(struct tevent_fd *fde) +{ + struct tevent_context *ev = fde->event_ctx; + struct port_event_context *port_ev = NULL; + struct tevent_fd *mpx_fde = NULL; + int flags = (int)fde->flags; + + if (ev == NULL) { + return tevent_common_fd_destructor(fde); + } + + port_ev = talloc_get_type_abort(ev->additional_data, + struct port_event_context); + + DLIST_REMOVE(ev->fd_events, fde); + + if (fde->additional_flags & PORT_ADDITIONAL_FD_FLAG_HAS_MPX) { + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + + fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_HAS_MPX; + mpx_fde->additional_flags &= ~PORT_ADDITIONAL_FD_FLAG_HAS_MPX; + + fde->additional_data = NULL; + mpx_fde->additional_data = NULL; + + fde->additional_flags &= PORT_ADDITIONAL_FD_FLAG_HAS_ASSOCIATION; + } + + (void)port_check_reopen(port_ev); + + if (mpx_fde != NULL) { + (void)port_update_event(port_ev, mpx_fde); + } + + fde->flags = 0; + (void)port_update_event(port_ev, fde); + fde->flags = flags; + + return tevent_common_fd_destructor(fde); +} + +/* + add a fd based event + return NULL on failure (memory allocation error) +*/ +static struct tevent_fd *port_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 port_event_context *port_ev = + talloc_get_type_abort(ev->additional_data, + struct port_event_context); + struct tevent_fd *fde; + + fde = tevent_common_add_fd(ev, mem_ctx, fd, flags, + handler, private_data, + handler_name, location); + if (!fde) { + return NULL; + } + + talloc_set_destructor(fde, port_event_fd_destructor); + + if (port_check_reopen(port_ev) != 0) { + TALLOC_FREE(fde); + return NULL; + } + + if (port_update_event(port_ev, fde) != 0) { + TALLOC_FREE(fde); + return NULL; + } + + return fde; +} + +/* + set the fd event flags +*/ +static void port_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags) +{ + struct tevent_context *ev; + struct port_event_context *port_ev; + + if (fde->flags == flags) { + return; + } + + ev = fde->event_ctx; + port_ev = talloc_get_type_abort(ev->additional_data, + struct port_event_context); + + fde->flags = flags; + + (void)port_check_reopen(port_ev); + (void)port_update_event(port_ev, fde); +} + +/* + do a single event loop using the events defined in ev +*/ +static int port_event_loop_once(struct tevent_context *ev, const char *location) +{ + struct port_event_context *port_ev = talloc_get_type(ev->additional_data, + struct port_event_context); + struct timeval tval; + + if (ev->signal_events && + tevent_common_check_signal(ev)) { + return 0; + } + + if (ev->threaded_contexts != NULL) { + tevent_common_threaded_activate_immediate(ev); + } + + 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; + } + + if (port_check_reopen(port_ev) != 0) { + errno = EINVAL; + return -1; + } + return port_event_loop(port_ev, &tval); +} + +static const struct tevent_ops port_event_ops = { + .context_init = port_event_context_init, + .add_fd = port_event_add_fd, + .set_fd_close_fn = tevent_common_fd_set_close_fn, + .get_fd_flags = tevent_common_fd_get_flags, + .set_fd_flags = port_event_set_fd_flags, + .add_timer = tevent_common_add_timer_v2, + .schedule_immediate = tevent_common_schedule_immediate, + .add_signal = tevent_common_add_signal, + .loop_once = port_event_loop_once, + .loop_wait = tevent_common_loop_wait, +}; + +_PRIVATE_ bool tevent_port_init(void) +{ + if (!tevent_register_backend("port", &port_event_ops)) { + return false; + } + tevent_set_default_backend("port"); + return true; +} diff --git a/lib/tevent/tevent_queue.c b/lib/tevent/tevent_queue.c new file mode 100644 index 0000000..dffe30f --- /dev/null +++ b/lib/tevent/tevent_queue.c @@ -0,0 +1,402 @@ +/* + Unix SMB/CIFS implementation. + Infrastructure for async requests + Copyright (C) Volker Lendecke 2008 + Copyright (C) Stefan Metzmacher 2009 + + ** 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 "replace.h" +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +struct tevent_queue_entry { + struct tevent_queue_entry *prev, *next; + struct tevent_queue *queue; + + bool triggered; + + struct tevent_req *req; + struct tevent_context *ev; + + tevent_queue_trigger_fn_t trigger; + void *private_data; + uint64_t tag; +}; + +struct tevent_queue { + const char *name; + const char *location; + + bool running; + struct tevent_immediate *immediate; + + size_t length; + struct tevent_queue_entry *list; +}; + +static void tevent_queue_immediate_trigger(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_data); + +static int tevent_queue_entry_destructor(struct tevent_queue_entry *e) +{ + struct tevent_queue *q = e->queue; + + if (!q) { + return 0; + } + + tevent_trace_queue_callback(q->list->ev, e, TEVENT_EVENT_TRACE_DETACH); + DLIST_REMOVE(q->list, e); + q->length--; + + if (!q->running) { + return 0; + } + + if (!q->list) { + return 0; + } + + if (q->list->triggered) { + return 0; + } + + tevent_schedule_immediate(q->immediate, + q->list->ev, + tevent_queue_immediate_trigger, + q); + + return 0; +} + +static int tevent_queue_destructor(struct tevent_queue *q) +{ + q->running = false; + + while (q->list) { + struct tevent_queue_entry *e = q->list; + talloc_free(e); + } + + return 0; +} + +struct tevent_queue *_tevent_queue_create(TALLOC_CTX *mem_ctx, + const char *name, + const char *location) +{ + struct tevent_queue *queue; + + queue = talloc_zero(mem_ctx, struct tevent_queue); + if (!queue) { + return NULL; + } + + queue->name = talloc_strdup(queue, name); + if (!queue->name) { + talloc_free(queue); + return NULL; + } + queue->immediate = tevent_create_immediate(queue); + if (!queue->immediate) { + talloc_free(queue); + return NULL; + } + + queue->location = location; + + /* queue is running by default */ + queue->running = true; + + talloc_set_destructor(queue, tevent_queue_destructor); + return queue; +} + +static void tevent_queue_immediate_trigger(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_data) +{ + struct tevent_queue *q = + talloc_get_type_abort(private_data, + struct tevent_queue); + + if (!q->running) { + return; + } + + if (!q->list) { + return; + } + + tevent_trace_queue_callback(ev, q->list, + TEVENT_EVENT_TRACE_BEFORE_HANDLER); + q->list->triggered = true; + q->list->trigger(q->list->req, q->list->private_data); +} + +static void tevent_queue_noop_trigger(struct tevent_req *req, + void *_private_data) +{ + /* this is doing nothing but blocking the queue */ +} + +static struct tevent_queue_entry *tevent_queue_add_internal( + struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data, + bool allow_direct) +{ + struct tevent_queue_entry *e; + + e = talloc_zero(req, struct tevent_queue_entry); + if (e == NULL) { + return NULL; + } + + /* + * if there is no trigger, it is just a blocker + */ + if (trigger == NULL) { + trigger = tevent_queue_noop_trigger; + } + + e->queue = queue; + e->req = req; + e->ev = ev; + e->trigger = trigger; + e->private_data = private_data; + + if (queue->length > 0) { + /* + * if there are already entries in the + * queue do not optimize. + */ + allow_direct = false; + } + + if (req->async.fn != NULL) { + /* + * If the caller wants to optimize for the + * empty queue case, call the trigger only + * if there is no callback defined for the + * request yet. + */ + allow_direct = false; + } + + DLIST_ADD_END(queue->list, e); + queue->length++; + talloc_set_destructor(e, tevent_queue_entry_destructor); + tevent_trace_queue_callback(ev, e, TEVENT_EVENT_TRACE_ATTACH); + + if (!queue->running) { + return e; + } + + if (queue->list->triggered) { + return e; + } + + /* + * If allowed we directly call the trigger + * avoiding possible delays caused by + * an immediate event. + */ + if (allow_direct) { + tevent_trace_queue_callback(ev, + queue->list, + TEVENT_EVENT_TRACE_BEFORE_HANDLER); + queue->list->triggered = true; + queue->list->trigger(queue->list->req, + queue->list->private_data); + return e; + } + + tevent_schedule_immediate(queue->immediate, + queue->list->ev, + tevent_queue_immediate_trigger, + queue); + + return e; +} + +bool tevent_queue_add(struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data) +{ + struct tevent_queue_entry *e; + + e = tevent_queue_add_internal(queue, ev, req, + trigger, private_data, false); + if (e == NULL) { + return false; + } + + return true; +} + +struct tevent_queue_entry *tevent_queue_add_entry( + struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data) +{ + return tevent_queue_add_internal(queue, ev, req, + trigger, private_data, false); +} + +struct tevent_queue_entry *tevent_queue_add_optimize_empty( + struct tevent_queue *queue, + struct tevent_context *ev, + struct tevent_req *req, + tevent_queue_trigger_fn_t trigger, + void *private_data) +{ + return tevent_queue_add_internal(queue, ev, req, + trigger, private_data, true); +} + +void tevent_queue_entry_untrigger(struct tevent_queue_entry *entry) +{ + if (entry->queue->running) { + abort(); + } + + if (entry->queue->list != entry) { + abort(); + } + + entry->triggered = false; +} + +void tevent_queue_start(struct tevent_queue *queue) +{ + if (queue->running) { + /* already started */ + return; + } + + queue->running = true; + + if (!queue->list) { + return; + } + + if (queue->list->triggered) { + return; + } + + tevent_schedule_immediate(queue->immediate, + queue->list->ev, + tevent_queue_immediate_trigger, + queue); +} + +void tevent_queue_stop(struct tevent_queue *queue) +{ + queue->running = false; +} + +size_t tevent_queue_length(struct tevent_queue *queue) +{ + return queue->length; +} + +bool tevent_queue_running(struct tevent_queue *queue) +{ + return queue->running; +} + +struct tevent_queue_wait_state { + uint8_t dummy; +}; + +static void tevent_queue_wait_trigger(struct tevent_req *req, + void *private_data); + +struct tevent_req *tevent_queue_wait_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct tevent_queue *queue) +{ + struct tevent_req *req; + struct tevent_queue_wait_state *state; + bool ok; + + req = tevent_req_create(mem_ctx, &state, + struct tevent_queue_wait_state); + if (req == NULL) { + return NULL; + } + + ok = tevent_queue_add(queue, ev, req, + tevent_queue_wait_trigger, + NULL); + if (!ok) { + tevent_req_oom(req); + return tevent_req_post(req, ev); + } + + return req; +} + +static void tevent_queue_wait_trigger(struct tevent_req *req, + void *private_data) +{ + tevent_req_done(req); +} + +bool tevent_queue_wait_recv(struct tevent_req *req) +{ + enum tevent_req_state state; + uint64_t err; + + if (tevent_req_is_error(req, &state, &err)) { + tevent_req_received(req); + return false; + } + + tevent_req_received(req); + return true; +} + +void tevent_queue_entry_set_tag(struct tevent_queue_entry *qe, uint64_t tag) +{ + if (qe == NULL) { + return; + } + + qe->tag = tag; +} + +uint64_t tevent_queue_entry_get_tag(const struct tevent_queue_entry *qe) +{ + if (qe == NULL) { + return 0; + } + + return qe->tag; +} diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c new file mode 100644 index 0000000..7821d9a --- /dev/null +++ b/lib/tevent/tevent_req.c @@ -0,0 +1,570 @@ +/* + Unix SMB/CIFS implementation. + Infrastructure for async requests + Copyright (C) Volker Lendecke 2008 + Copyright (C) Stefan Metzmacher 2009 + + ** 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 "replace.h" +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +char *tevent_req_default_print(struct tevent_req *req, TALLOC_CTX *mem_ctx) +{ + return talloc_asprintf(mem_ctx, + "tevent_req[%p/%s]: state[%d] error[%lld (0x%llX)] " + " state[%s (%p)] timer[%p] finish[%s]", + req, req->internal.create_location, + req->internal.state, + (unsigned long long)req->internal.error, + (unsigned long long)req->internal.error, + req->internal.private_type, + req->data, + req->internal.timer, + req->internal.finish_location + ); +} + +char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req) +{ + if (req == NULL) { + return talloc_strdup(mem_ctx, "tevent_req[NULL]"); + } + + if (!req->private_print) { + return tevent_req_default_print(req, mem_ctx); + } + + return req->private_print(req, mem_ctx); +} + +static int tevent_req_destructor(struct tevent_req *req); + +struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, + void *pdata, + size_t data_size, + const char *type, + const char *location) +{ + struct tevent_req *req; + struct tevent_req *parent; + void **ppdata = (void **)pdata; + void *data; + size_t payload; + + payload = sizeof(struct tevent_immediate) + data_size; + if (payload < sizeof(struct tevent_immediate)) { + /* overflow */ + return NULL; + } + + req = talloc_pooled_object( + mem_ctx, struct tevent_req, 2, + sizeof(struct tevent_immediate) + data_size); + if (req == NULL) { + return NULL; + } + + *req = (struct tevent_req) { + .internal = { + .private_type = type, + .create_location = location, + .state = TEVENT_REQ_IN_PROGRESS, + .trigger = tevent_create_immediate(req), + }, + }; + + data = talloc_zero_size(req, data_size); + + /* + * No need to check for req->internal.trigger!=NULL or + * data!=NULL, this can't fail: talloc_pooled_object has + * already allocated sufficient memory. + */ + + talloc_set_name_const(data, type); + + req->data = data; + + talloc_set_destructor(req, tevent_req_destructor); + + parent = talloc_get_type(talloc_parent(mem_ctx), struct tevent_req); + if ((parent != NULL) && (parent->internal.profile != NULL)) { + bool ok = tevent_req_set_profile(req); + + if (!ok) { + TALLOC_FREE(req); + return NULL; + } + req->internal.profile->parent = parent->internal.profile; + DLIST_ADD_END(parent->internal.profile->subprofiles, + req->internal.profile); + } + + *ppdata = data; + return req; +} + +static int tevent_req_destructor(struct tevent_req *req) +{ + tevent_req_received(req); + return 0; +} + +void _tevent_req_notify_callback(struct tevent_req *req, const char *location) +{ + req->internal.finish_location = location; + if (req->internal.defer_callback_ev) { + (void)tevent_req_post(req, req->internal.defer_callback_ev); + req->internal.defer_callback_ev = NULL; + return; + } + if (req->async.fn != NULL) { + req->async.fn(req); + } +} + +static void tevent_req_cleanup(struct tevent_req *req) +{ + if (req->private_cleanup.fn == NULL) { + return; + } + + if (req->private_cleanup.state >= req->internal.state) { + /* + * Don't call the cleanup_function multiple times for the same + * state recursively + */ + return; + } + + req->private_cleanup.state = req->internal.state; + req->private_cleanup.fn(req, req->internal.state); +} + +static void tevent_req_finish(struct tevent_req *req, + enum tevent_req_state state, + const char *location) +{ + struct tevent_req_profile *p; + /* + * make sure we do not timeout after + * the request was already finished + */ + TALLOC_FREE(req->internal.timer); + + req->internal.state = state; + req->internal.finish_location = location; + + tevent_req_cleanup(req); + + p = req->internal.profile; + + if (p != NULL) { + p->stop_location = location; + p->stop_time = tevent_timeval_current(); + p->state = state; + p->user_error = req->internal.error; + + if (p->parent != NULL) { + talloc_steal(p->parent, p); + req->internal.profile = NULL; + } + } + + _tevent_req_notify_callback(req, location); +} + +void _tevent_req_done(struct tevent_req *req, + const char *location) +{ + tevent_req_finish(req, TEVENT_REQ_DONE, location); +} + +bool _tevent_req_error(struct tevent_req *req, + uint64_t error, + const char *location) +{ + if (error == 0) { + return false; + } + + req->internal.error = error; + tevent_req_finish(req, TEVENT_REQ_USER_ERROR, location); + return true; +} + +void _tevent_req_oom(struct tevent_req *req, const char *location) +{ + tevent_req_finish(req, TEVENT_REQ_NO_MEMORY, location); +} + +bool _tevent_req_nomem(const void *p, + struct tevent_req *req, + const char *location) +{ + if (p != NULL) { + return false; + } + _tevent_req_oom(req, location); + return true; +} + +/** + * @internal + * + * @brief Immediate event callback. + * + * @param[in] ev The event context to use. + * + * @param[in] im The immediate event. + * + * @param[in] priv The async request to be finished. + */ +static void tevent_req_trigger(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_data) +{ + struct tevent_req *req = + talloc_get_type_abort(private_data, + struct tevent_req); + + tevent_req_finish(req, req->internal.state, + req->internal.finish_location); +} + +struct tevent_req *tevent_req_post(struct tevent_req *req, + struct tevent_context *ev) +{ + tevent_schedule_immediate(req->internal.trigger, + ev, tevent_req_trigger, req); + return req; +} + +void tevent_req_defer_callback(struct tevent_req *req, + struct tevent_context *ev) +{ + req->internal.defer_callback_ev = ev; +} + +bool tevent_req_is_in_progress(struct tevent_req *req) +{ + if (req->internal.state == TEVENT_REQ_IN_PROGRESS) { + return true; + } + + return false; +} + +void tevent_req_received(struct tevent_req *req) +{ + talloc_set_destructor(req, NULL); + + req->private_print = NULL; + req->private_cancel = NULL; + + TALLOC_FREE(req->internal.trigger); + TALLOC_FREE(req->internal.timer); + + req->internal.state = TEVENT_REQ_RECEIVED; + + tevent_req_cleanup(req); + + TALLOC_FREE(req->data); +} + +bool tevent_req_poll(struct tevent_req *req, + struct tevent_context *ev) +{ + while (tevent_req_is_in_progress(req)) { + int ret; + + ret = tevent_loop_once(ev); + if (ret != 0) { + return false; + } + } + + return true; +} + +bool tevent_req_is_error(struct tevent_req *req, enum tevent_req_state *state, + uint64_t *error) +{ + if (req->internal.state == TEVENT_REQ_DONE) { + return false; + } + if (req->internal.state == TEVENT_REQ_USER_ERROR) { + *error = req->internal.error; + } + *state = req->internal.state; + return true; +} + +static void tevent_req_timedout(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval now, + void *private_data) +{ + struct tevent_req *req = + talloc_get_type_abort(private_data, + struct tevent_req); + + TALLOC_FREE(req->internal.timer); + + tevent_req_finish(req, TEVENT_REQ_TIMED_OUT, __FUNCTION__); +} + +bool tevent_req_set_endtime(struct tevent_req *req, + struct tevent_context *ev, + struct timeval endtime) +{ + TALLOC_FREE(req->internal.timer); + + req->internal.timer = tevent_add_timer(ev, req, endtime, + tevent_req_timedout, + req); + if (tevent_req_nomem(req->internal.timer, req)) { + return false; + } + + return true; +} + +void tevent_req_reset_endtime(struct tevent_req *req) +{ + TALLOC_FREE(req->internal.timer); +} + +void tevent_req_set_callback(struct tevent_req *req, tevent_req_fn fn, void *pvt) +{ + req->async.fn = fn; + req->async.private_data = pvt; +} + +void *_tevent_req_callback_data(struct tevent_req *req) +{ + return req->async.private_data; +} + +void *_tevent_req_data(struct tevent_req *req) +{ + return req->data; +} + +void tevent_req_set_print_fn(struct tevent_req *req, tevent_req_print_fn fn) +{ + req->private_print = fn; +} + +void tevent_req_set_cancel_fn(struct tevent_req *req, tevent_req_cancel_fn fn) +{ + req->private_cancel = fn; +} + +bool _tevent_req_cancel(struct tevent_req *req, const char *location) +{ + if (req->private_cancel == NULL) { + return false; + } + + return req->private_cancel(req); +} + +void tevent_req_set_cleanup_fn(struct tevent_req *req, tevent_req_cleanup_fn fn) +{ + req->private_cleanup.state = req->internal.state; + req->private_cleanup.fn = fn; +} + +static int tevent_req_profile_destructor(struct tevent_req_profile *p); + +bool tevent_req_set_profile(struct tevent_req *req) +{ + struct tevent_req_profile *p; + + if (req->internal.profile != NULL) { + tevent_req_error(req, EINVAL); + return false; + } + + p = tevent_req_profile_create(req); + + if (tevent_req_nomem(p, req)) { + return false; + } + + p->req_name = talloc_get_name(req->data); + p->start_location = req->internal.create_location; + p->start_time = tevent_timeval_current(); + + req->internal.profile = p; + + return true; +} + +static int tevent_req_profile_destructor(struct tevent_req_profile *p) +{ + if (p->parent != NULL) { + DLIST_REMOVE(p->parent->subprofiles, p); + p->parent = NULL; + } + + while (p->subprofiles != NULL) { + p->subprofiles->parent = NULL; + DLIST_REMOVE(p->subprofiles, p->subprofiles); + } + + return 0; +} + +struct tevent_req_profile *tevent_req_move_profile(struct tevent_req *req, + TALLOC_CTX *mem_ctx) +{ + return talloc_move(mem_ctx, &req->internal.profile); +} + +const struct tevent_req_profile *tevent_req_get_profile( + struct tevent_req *req) +{ + return req->internal.profile; +} + +void tevent_req_profile_get_name(const struct tevent_req_profile *profile, + const char **req_name) +{ + if (req_name != NULL) { + *req_name = profile->req_name; + } +} + +void tevent_req_profile_get_start(const struct tevent_req_profile *profile, + const char **start_location, + struct timeval *start_time) +{ + if (start_location != NULL) { + *start_location = profile->start_location; + } + if (start_time != NULL) { + *start_time = profile->start_time; + } +} + +void tevent_req_profile_get_stop(const struct tevent_req_profile *profile, + const char **stop_location, + struct timeval *stop_time) +{ + if (stop_location != NULL) { + *stop_location = profile->stop_location; + } + if (stop_time != NULL) { + *stop_time = profile->stop_time; + } +} + +void tevent_req_profile_get_status(const struct tevent_req_profile *profile, + pid_t *pid, + enum tevent_req_state *state, + uint64_t *user_error) +{ + if (pid != NULL) { + *pid = profile->pid; + } + if (state != NULL) { + *state = profile->state; + } + if (user_error != NULL) { + *user_error = profile->user_error; + } +} + +const struct tevent_req_profile *tevent_req_profile_get_subprofiles( + const struct tevent_req_profile *profile) +{ + return profile->subprofiles; +} + +const struct tevent_req_profile *tevent_req_profile_next( + const struct tevent_req_profile *profile) +{ + return profile->next; +} + +struct tevent_req_profile *tevent_req_profile_create(TALLOC_CTX *mem_ctx) +{ + struct tevent_req_profile *result; + + result = talloc_zero(mem_ctx, struct tevent_req_profile); + if (result == NULL) { + return NULL; + } + talloc_set_destructor(result, tevent_req_profile_destructor); + + return result; +} + +bool tevent_req_profile_set_name(struct tevent_req_profile *profile, + const char *req_name) +{ + profile->req_name = talloc_strdup(profile, req_name); + return (profile->req_name != NULL); +} + +bool tevent_req_profile_set_start(struct tevent_req_profile *profile, + const char *start_location, + struct timeval start_time) +{ + profile->start_time = start_time; + + profile->start_location = talloc_strdup(profile, start_location); + return (profile->start_location != NULL); +} + +bool tevent_req_profile_set_stop(struct tevent_req_profile *profile, + const char *stop_location, + struct timeval stop_time) +{ + profile->stop_time = stop_time; + + profile->stop_location = talloc_strdup(profile, stop_location); + return (profile->stop_location != NULL); +} + +void tevent_req_profile_set_status(struct tevent_req_profile *profile, + pid_t pid, + enum tevent_req_state state, + uint64_t user_error) +{ + profile->pid = pid; + profile->state = state; + profile->user_error = user_error; +} + +void tevent_req_profile_append_sub(struct tevent_req_profile *parent_profile, + struct tevent_req_profile **sub_profile) +{ + struct tevent_req_profile *sub; + + sub = talloc_move(parent_profile, sub_profile); + + sub->parent = parent_profile; + DLIST_ADD_END(parent_profile->subprofiles, sub); +} diff --git a/lib/tevent/tevent_signal.c b/lib/tevent/tevent_signal.c new file mode 100644 index 0000000..eab3654 --- /dev/null +++ b/lib/tevent/tevent_signal.c @@ -0,0 +1,539 @@ +/* + Unix SMB/CIFS implementation. + + common events code for signal events + + Copyright (C) Andrew Tridgell 2007 + + ** 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 "replace.h" +#include "system/filesys.h" +#include "system/wait.h" +#define TEVENT_DEPRECATED 1 +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +/* 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> + for this. */ + +#define TEVENT_SA_INFO_QUEUE_COUNT 256 + +size_t tevent_num_signals(void) +{ + return TEVENT_NUM_SIGNALS; +} + +size_t tevent_sa_info_queue_count(void) +{ + return TEVENT_SA_INFO_QUEUE_COUNT; +} + +struct tevent_sigcounter { + uint32_t count; + uint32_t seen; +}; + +#if defined(HAVE___SYNC_FETCH_AND_ADD) +#define TEVENT_SIG_INCREMENT(s) __sync_fetch_and_add(&((s).count), 1) +#elif defined(HAVE_ATOMIC_ADD_32) +#define TEVENT_SIG_INCREMENT(s) atomic_add_32(&((s).count), 1) +#else +#define TEVENT_SIG_INCREMENT(s) (s).count++ +#endif +#define TEVENT_SIG_SEEN(s, n) (s).seen += (n) +#define TEVENT_SIG_PENDING(s) ((s).seen != (s).count) + +struct tevent_common_signal_list { + struct tevent_common_signal_list *prev, *next; + struct tevent_signal *se; +}; + +/* + the poor design of signals means that this table must be static global +*/ +static struct tevent_sig_state { + struct tevent_common_signal_list *sig_handlers[TEVENT_NUM_SIGNALS+1]; + struct sigaction *oldact[TEVENT_NUM_SIGNALS+1]; + struct tevent_sigcounter signal_count[TEVENT_NUM_SIGNALS+1]; + struct tevent_sigcounter got_signal; +#ifdef SA_SIGINFO + /* with SA_SIGINFO we get quite a lot of info per signal */ + siginfo_t *sig_info[TEVENT_NUM_SIGNALS+1]; + struct tevent_sigcounter sig_blocked[TEVENT_NUM_SIGNALS+1]; +#endif +} *sig_state; + +/* + return number of sigcounter events not processed yet +*/ +static uint32_t tevent_sig_count(struct tevent_sigcounter s) +{ + return s.count - s.seen; +} + +/* + signal handler - redirects to registered signals +*/ +static void tevent_common_signal_handler(int signum) +{ + struct tevent_common_signal_list *sl; + struct tevent_context *ev = NULL; + int saved_errno = errno; + + TEVENT_SIG_INCREMENT(sig_state->signal_count[signum]); + TEVENT_SIG_INCREMENT(sig_state->got_signal); + + /* Write to each unique event context. */ + for (sl = sig_state->sig_handlers[signum]; sl; sl = sl->next) { + if (sl->se->event_ctx && sl->se->event_ctx != ev) { + ev = sl->se->event_ctx; + tevent_common_wakeup(ev); + } + } + + errno = saved_errno; +} + +#ifdef SA_SIGINFO +/* + signal handler with SA_SIGINFO - redirects to registered signals +*/ +static void tevent_common_signal_handler_info(int signum, siginfo_t *info, + void *uctx) +{ + uint32_t count = tevent_sig_count(sig_state->signal_count[signum]); + /* sig_state->signal_count[signum].seen % TEVENT_SA_INFO_QUEUE_COUNT + * is the base of the unprocessed signals in the ringbuffer. */ + uint32_t ofs = (sig_state->signal_count[signum].seen + count) % + TEVENT_SA_INFO_QUEUE_COUNT; + sig_state->sig_info[signum][ofs] = *info; + + tevent_common_signal_handler(signum); + + /* handle SA_SIGINFO */ + 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]); + } +} +#endif + +static int tevent_common_signal_list_destructor(struct tevent_common_signal_list *sl) +{ + if (sig_state->sig_handlers[sl->se->signum]) { + DLIST_REMOVE(sig_state->sig_handlers[sl->se->signum], sl); + } + return 0; +} + +/* + destroy a signal event +*/ +static int tevent_signal_destructor(struct tevent_signal *se) +{ + if (se->destroyed) { + tevent_common_check_double_free(se, "tevent_signal double free"); + goto done; + } + se->destroyed = true; + + TALLOC_FREE(se->additional_data); + + if (se->event_ctx != NULL) { + tevent_trace_signal_callback(se->event_ctx, se, TEVENT_EVENT_TRACE_DETACH); + DLIST_REMOVE(se->event_ctx->signal_events, se); + } + + if (sig_state->sig_handlers[se->signum] == NULL) { + /* restore old handler, if any */ + if (sig_state->oldact[se->signum]) { + sigaction(se->signum, sig_state->oldact[se->signum], NULL); + TALLOC_FREE(sig_state->oldact[se->signum]); + } +#ifdef SA_SIGINFO + if (se->sa_flags & SA_SIGINFO) { + if (sig_state->sig_info[se->signum]) { + TALLOC_FREE(sig_state->sig_info[se->signum]); + } + } +#endif + } + + se->event_ctx = NULL; +done: + if (se->busy) { + return -1; + } + se->wrapper = NULL; + + return 0; +} + +/* + add a signal event + return NULL on failure (memory allocation error) +*/ +struct tevent_signal *tevent_common_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) +{ + struct tevent_signal *se; + struct tevent_common_signal_list *sl; + sigset_t set, oldset; + int ret; + + ret = tevent_common_wakeup_init(ev); + if (ret != 0) { + errno = ret; + return NULL; + } + + if (signum >= TEVENT_NUM_SIGNALS) { + errno = EINVAL; + return NULL; + } + + /* the sig_state needs to be on a global context as it can last across + multiple event contexts */ + if (sig_state == NULL) { + sig_state = talloc_zero(NULL, struct tevent_sig_state); + if (sig_state == NULL) { + return NULL; + } + } + + se = talloc_zero(mem_ctx?mem_ctx:ev, struct tevent_signal); + if (se == NULL) return NULL; + + sl = talloc_zero(se, struct tevent_common_signal_list); + if (!sl) { + talloc_free(se); + return NULL; + } + sl->se = se; + + *se = (struct tevent_signal) { + .event_ctx = ev, + .signum = signum, + .sa_flags = sa_flags, + .handler = handler, + .private_data = private_data, + .handler_name = handler_name, + .location = location, + .additional_data= sl, + }; + + /* Ensure, no matter the destruction order, that we always have a handle on the global sig_state */ + if (!talloc_reference(se, sig_state)) { + talloc_free(se); + return NULL; + } + + /* only install a signal handler if not already installed */ + if (sig_state->sig_handlers[signum] == NULL) { + struct sigaction act; + ZERO_STRUCT(act); + act.sa_handler = tevent_common_signal_handler; + act.sa_flags = sa_flags; +#ifdef SA_SIGINFO + if (sa_flags & SA_SIGINFO) { + act.sa_handler = NULL; + act.sa_sigaction = tevent_common_signal_handler_info; + if (sig_state->sig_info[signum] == NULL) { + sig_state->sig_info[signum] = + talloc_zero_array(sig_state, siginfo_t, + TEVENT_SA_INFO_QUEUE_COUNT); + if (sig_state->sig_info[signum] == NULL) { + talloc_free(se); + return NULL; + } + } + } +#endif + sig_state->oldact[signum] = talloc_zero(sig_state, struct sigaction); + if (sig_state->oldact[signum] == NULL) { + talloc_free(se); + return NULL; + } + if (sigaction(signum, &act, sig_state->oldact[signum]) == -1) { + talloc_free(sig_state->oldact[signum]); + sig_state->oldact[signum] = NULL; + talloc_free(se); + return NULL; + } + } + + DLIST_ADD(se->event_ctx->signal_events, se); + + /* Make sure the signal doesn't come in while we're mangling list. */ + sigemptyset(&set); + sigaddset(&set, signum); + sigprocmask(SIG_BLOCK, &set, &oldset); + tevent_trace_signal_callback(se->event_ctx, se, TEVENT_EVENT_TRACE_ATTACH); + DLIST_ADD(sig_state->sig_handlers[signum], sl); + sigprocmask(SIG_SETMASK, &oldset, NULL); + + talloc_set_destructor(se, tevent_signal_destructor); + talloc_set_destructor(sl, tevent_common_signal_list_destructor); + + return se; +} + +int tevent_common_invoke_signal_handler(struct tevent_signal *se, + int signum, int count, void *siginfo, + bool *removed) +{ + struct tevent_context *handler_ev = se->event_ctx; + bool remove = false; + + if (removed != NULL) { + *removed = false; + } + + if (se->event_ctx == NULL) { + return 0; + } + + se->busy = true; + if (se->wrapper != NULL) { + handler_ev = se->wrapper->wrap_ev; + + tevent_wrapper_push_use_internal(handler_ev, se->wrapper); + se->wrapper->ops->before_signal_handler( + se->wrapper->wrap_ev, + se->wrapper->private_state, + se->wrapper->main_ev, + se, + signum, + count, + siginfo, + se->handler_name, + se->location); + } + tevent_trace_signal_callback(se->event_ctx, se, TEVENT_EVENT_TRACE_BEFORE_HANDLER); + se->handler(handler_ev, se, signum, count, siginfo, se->private_data); + if (se->wrapper != NULL) { + se->wrapper->ops->after_signal_handler( + se->wrapper->wrap_ev, + se->wrapper->private_state, + se->wrapper->main_ev, + se, + signum, + count, + siginfo, + se->handler_name, + se->location); + tevent_wrapper_pop_use_internal(handler_ev, se->wrapper); + } + se->busy = false; + +#ifdef SA_RESETHAND + if (se->sa_flags & SA_RESETHAND) { + remove = true; + } +#endif + + if (se->destroyed) { + talloc_set_destructor(se, NULL); + remove = true; + } + + if (remove) { + TALLOC_FREE(se); + if (removed != NULL) { + *removed = true; + } + } + + return 0; +} + +/* + check if a signal is pending + return != 0 if a signal was pending +*/ +int tevent_common_check_signal(struct tevent_context *ev) +{ + int i; + + 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]; + uint32_t count = tevent_sig_count(counter); + int ret; +#ifdef SA_SIGINFO + /* Ensure we null out any stored siginfo_t entries + * after processing for debugging purposes. */ + bool clear_processed_siginfo = false; +#endif + + if (count == 0) { + continue; + } + for (sl=sig_state->sig_handlers[i];sl;sl=next) { + struct tevent_signal *se = sl->se; + + next = sl->next; + +#ifdef SA_SIGINFO + if (se->sa_flags & SA_SIGINFO) { + uint32_t j; + + clear_processed_siginfo = true; + + for (j=0;j<count;j++) { + /* sig_state->signal_count[i].seen + * % TEVENT_SA_INFO_QUEUE_COUNT is + * the base position of the unprocessed + * signals in the ringbuffer. */ + uint32_t ofs = (counter.seen + j) + % TEVENT_SA_INFO_QUEUE_COUNT; + bool removed = false; + + ret = tevent_common_invoke_signal_handler( + se, i, 1, + (void*)&sig_state->sig_info[i][ofs], + &removed); + if (ret != 0) { + tevent_abort(ev, "tevent_common_invoke_signal_handler() failed"); + } + if (removed) { + break; + } + } + continue; + } +#endif + + ret = tevent_common_invoke_signal_handler(se, i, count, + NULL, NULL); + if (ret != 0) { + tevent_abort(ev, "tevent_common_invoke_signal_handler() failed"); + } + } + +#ifdef SA_SIGINFO + if (clear_processed_siginfo && sig_state->sig_info[i] != NULL) { + uint32_t j; + for (j=0;j<count;j++) { + uint32_t ofs = (counter.seen + j) + % TEVENT_SA_INFO_QUEUE_COUNT; + memset((void*)&sig_state->sig_info[i][ofs], + '\0', + sizeof(siginfo_t)); + } + } +#endif + + TEVENT_SIG_SEEN(sig_state->signal_count[i], count); + TEVENT_SIG_SEEN(sig_state->got_signal, count); + +#ifdef SA_SIGINFO + if (TEVENT_SIG_PENDING(sig_state->sig_blocked[i])) { + /* We'd filled the queue, unblock the + signal now the queue is empty again. + Note we MUST do this after the + TEVENT_SIG_SEEN(sig_state->signal_count[i], count) + call to prevent a new signal running + out of room in the sig_state->sig_info[i][] + ring buffer. */ + sigset_t set; + sigemptyset(&set); + sigaddset(&set, i); + TEVENT_SIG_SEEN(sig_state->sig_blocked[i], + tevent_sig_count(sig_state->sig_blocked[i])); + sigprocmask(SIG_UNBLOCK, &set, NULL); + } +#endif + } + + return 1; +} + +void tevent_cleanup_pending_signal_handlers(struct tevent_signal *se) +{ + tevent_signal_destructor(se); + talloc_set_destructor(se, NULL); + return; +} + +void tevent_signal_set_tag(struct tevent_signal *se, uint64_t tag) +{ + if (se == NULL) { + return; + } + + se->tag = tag; +} + +uint64_t tevent_signal_get_tag(const struct tevent_signal *se) +{ + if (se == NULL) { + return 0; + } + + return se->tag; +} diff --git a/lib/tevent/tevent_standard.c b/lib/tevent/tevent_standard.c new file mode 100644 index 0000000..3872020 --- /dev/null +++ b/lib/tevent/tevent_standard.c @@ -0,0 +1,238 @@ +/* + Unix SMB/CIFS implementation. + main select loop and event handling + 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 + ** 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/>. +*/ + +/* + This is SAMBA's default event loop code + + - we try to use epoll if configure detected support for it + otherwise we use poll() + - if epoll is broken on the system or the kernel doesn't support it + at runtime we fallback to poll() +*/ + +#include "replace.h" +#include "tevent.h" +#include "tevent_util.h" +#include "tevent_internal.h" + +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, +}; + +/* + If this function gets called. epoll failed at runtime. + Move us to using poll instead. If we return false here, + caller should abort(). +*/ +#ifdef HAVE_EPOLL +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; + + 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; + } + + /* + * 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) { + bool ok; + + /* Re-add this event as a poll backend event. */ + ok = tevent_poll_event_add_fd_internal(ev, fde); + if (!ok) { + return false; + } + } + + return true; +} +#endif + +static int std_event_loop_once(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_once(ev, location); + /* + * If the above hasn't panicked due to an epoll interface failure, + * std_fallback_to_poll() wasn't called, and hasn't cleared epoll_ops to + * signify fallback to poll_ops. + */ + if (glue->epoll_ops != NULL) { + /* No fallback */ + return ret; + } + + 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; + } + + return glue->poll_ops->loop_once(ev, location); +} + +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 the above hasn't panicked due to an epoll interface failure, + * std_fallback_to_poll() wasn't called, and hasn't cleared epoll_ops to + * signify fallback to poll_ops. + */ + if (glue->epoll_ops != NULL) { + /* No fallback */ + return ret; + } + + return glue->poll_ops->loop_wait(ev, location); +} +/* + 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_glue *glue; + int ret; + + /* + * If this is the first initialization + * we need to set up the allocated ops + * pointers. + */ + + if (ev->ops == &std_event_ops) { + glue = talloc_zero(ev, struct std_event_glue); + if (glue == NULL) { + return -1; + } + + glue->epoll_ops = tevent_find_ops_byname("epoll"); + + glue->poll_ops = tevent_find_ops_byname("poll"); + if (glue->poll_ops == NULL) { + return -1; + } + + /* + * 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 (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; + + ret = glue->epoll_ops->context_init(ev); + if (ret == -1) { + goto fallback; + } +#ifdef HAVE_EPOLL + tevent_epoll_set_panic_fallback(ev, std_fallback_to_poll); +#endif + + return ret; + } + +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); +} + +_PRIVATE_ bool tevent_standard_init(void) +{ + return tevent_register_backend("standard", &std_event_ops); +} diff --git a/lib/tevent/tevent_threads.c b/lib/tevent/tevent_threads.c new file mode 100644 index 0000000..a89990f --- /dev/null +++ b/lib/tevent/tevent_threads.c @@ -0,0 +1,601 @@ +/* + tevent event library. + + Copyright (C) Jeremy Allison 2015 + + ** 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 "replace.h" +#include "system/filesys.h" +#include "talloc.h" +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +#ifdef HAVE_PTHREAD +#include "system/threads.h" + +struct tevent_immediate_list { + struct tevent_immediate_list *next, *prev; + tevent_immediate_handler_t handler; + struct tevent_immediate *im; + void *private_ptr; +}; + +struct tevent_thread_proxy { + pthread_mutex_t mutex; + struct tevent_context *dest_ev_ctx; + int read_fd; + int write_fd; + struct tevent_fd *pipe_read_fde; + /* Pending events list. */ + struct tevent_immediate_list *im_list; + /* Completed events list. */ + struct tevent_immediate_list *tofree_im_list; + struct tevent_immediate *free_im; +}; + +static void free_im_list(struct tevent_immediate_list **pp_list_head) +{ + struct tevent_immediate_list *im_entry = NULL; + struct tevent_immediate_list *im_next = NULL; + + for (im_entry = *pp_list_head; im_entry; im_entry = im_next) { + im_next = im_entry->next; + DLIST_REMOVE(*pp_list_head, im_entry); + TALLOC_FREE(im_entry); + } +} + +static void free_list_handler(struct tevent_context *ev, + struct tevent_immediate *im, + void *private_ptr) +{ + struct tevent_thread_proxy *tp = + talloc_get_type_abort(private_ptr, struct tevent_thread_proxy); + int ret; + + ret = pthread_mutex_lock(&tp->mutex); + if (ret != 0) { + abort(); + /* Notreached. */ + return; + } + + free_im_list(&tp->tofree_im_list); + + ret = pthread_mutex_unlock(&tp->mutex); + if (ret != 0) { + abort(); + /* Notreached. */ + return; + } +} + +static void schedule_immediate_functions(struct tevent_thread_proxy *tp) +{ + struct tevent_immediate_list *im_entry = NULL; + struct tevent_immediate_list *im_next = NULL; + + for (im_entry = tp->im_list; im_entry; im_entry = im_next) { + im_next = im_entry->next; + DLIST_REMOVE(tp->im_list, im_entry); + + tevent_schedule_immediate(im_entry->im, + tp->dest_ev_ctx, + im_entry->handler, + im_entry->private_ptr); + + /* Move from pending list to free list. */ + DLIST_ADD(tp->tofree_im_list, im_entry); + } + if (tp->tofree_im_list != NULL) { + /* + * Once the current immediate events + * are processed, we need to reschedule + * ourselves to free them. This works + * as tevent_schedule_immediate() + * always adds events to the *END* of + * the immediate events list. + */ + tevent_schedule_immediate(tp->free_im, + tp->dest_ev_ctx, + free_list_handler, + tp); + } +} + +static void pipe_read_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_ptr) +{ + struct tevent_thread_proxy *tp = + talloc_get_type_abort(private_ptr, struct tevent_thread_proxy); + ssize_t len = 64; + int ret; + + ret = pthread_mutex_lock(&tp->mutex); + if (ret != 0) { + abort(); + /* Notreached. */ + return; + } + + /* + * Clear out all data in the pipe. We + * don't really care if this returns -1. + */ + while (len == 64) { + char buf[64]; + len = read(tp->read_fd, buf, 64); + }; + + schedule_immediate_functions(tp); + + ret = pthread_mutex_unlock(&tp->mutex); + if (ret != 0) { + abort(); + /* Notreached. */ + return; + } +} + +static int tevent_thread_proxy_destructor(struct tevent_thread_proxy *tp) +{ + int ret; + + ret = pthread_mutex_lock(&tp->mutex); + if (ret != 0) { + abort(); + /* Notreached. */ + return 0; + } + + TALLOC_FREE(tp->pipe_read_fde); + + if (tp->read_fd != -1) { + (void)close(tp->read_fd); + tp->read_fd = -1; + } + if (tp->write_fd != -1) { + (void)close(tp->write_fd); + tp->write_fd = -1; + } + + /* Hmmm. It's probably an error if we get here with + any non-NULL immediate entries.. */ + + free_im_list(&tp->im_list); + free_im_list(&tp->tofree_im_list); + + TALLOC_FREE(tp->free_im); + + ret = pthread_mutex_unlock(&tp->mutex); + if (ret != 0) { + abort(); + /* Notreached. */ + return 0; + } + + ret = pthread_mutex_destroy(&tp->mutex); + if (ret != 0) { + abort(); + /* Notreached. */ + return 0; + } + + return 0; +} + +/* + * Create a struct that can be passed to other threads + * to allow them to signal the struct tevent_context * + * passed in. + */ + +struct tevent_thread_proxy *tevent_thread_proxy_create( + struct tevent_context *dest_ev_ctx) +{ + int ret; + int pipefds[2]; + struct tevent_thread_proxy *tp; + + if (dest_ev_ctx->wrapper.glue != NULL) { + /* + * stacking of wrappers is not supported + */ + tevent_debug(dest_ev_ctx->wrapper.glue->main_ev, + TEVENT_DEBUG_FATAL, + "%s() not allowed on a wrapper context\n", + __func__); + errno = EINVAL; + return NULL; + } + + tp = talloc_zero(dest_ev_ctx, struct tevent_thread_proxy); + if (tp == NULL) { + return NULL; + } + + ret = pthread_mutex_init(&tp->mutex, NULL); + if (ret != 0) { + goto fail; + } + + tp->dest_ev_ctx = dest_ev_ctx; + tp->read_fd = -1; + tp->write_fd = -1; + + talloc_set_destructor(tp, tevent_thread_proxy_destructor); + + ret = pipe(pipefds); + if (ret == -1) { + goto fail; + } + + tp->read_fd = pipefds[0]; + tp->write_fd = pipefds[1]; + + ret = ev_set_blocking(pipefds[0], false); + if (ret != 0) { + goto fail; + } + ret = ev_set_blocking(pipefds[1], false); + if (ret != 0) { + goto fail; + } + if (!ev_set_close_on_exec(pipefds[0])) { + goto fail; + } + if (!ev_set_close_on_exec(pipefds[1])) { + goto fail; + } + + tp->pipe_read_fde = tevent_add_fd(dest_ev_ctx, + tp, + tp->read_fd, + TEVENT_FD_READ, + pipe_read_handler, + tp); + if (tp->pipe_read_fde == NULL) { + goto fail; + } + + /* + * Create an immediate event to free + * completed lists. + */ + tp->free_im = tevent_create_immediate(tp); + if (tp->free_im == NULL) { + goto fail; + } + + return tp; + + fail: + + TALLOC_FREE(tp); + return NULL; +} + +/* + * This function schedules an immediate event to be called with argument + * *pp_private in the thread context of dest_ev_ctx. Caller doesn't + * wait for activation to take place, this is simply fire-and-forget. + * + * pp_im must be a pointer to an immediate event talloced on + * a context owned by the calling thread, or the NULL context. + * Ownership of *pp_im will be transfered to the tevent library. + * + * pp_private can be null, or contents of *pp_private must be + * talloc'ed memory on a context owned by the calling thread + * or the NULL context. If non-null, ownership of *pp_private will + * be transfered to the tevent library. + * + * If you want to return a message, have the destination use the + * same function call to send back to the caller. + */ + + +void tevent_thread_proxy_schedule(struct tevent_thread_proxy *tp, + struct tevent_immediate **pp_im, + tevent_immediate_handler_t handler, + void *pp_private_data) +{ + struct tevent_immediate_list *im_entry; + int ret; + char c; + ssize_t written; + + ret = pthread_mutex_lock(&tp->mutex); + if (ret != 0) { + abort(); + /* Notreached. */ + return; + } + + if (tp->write_fd == -1) { + /* In the process of being destroyed. Ignore. */ + goto end; + } + + /* Create a new immediate_list entry. MUST BE ON THE NULL CONTEXT */ + im_entry = talloc_zero(NULL, struct tevent_immediate_list); + if (im_entry == NULL) { + goto end; + } + + im_entry->handler = handler; + im_entry->im = talloc_move(im_entry, pp_im); + + if (pp_private_data != NULL) { + void **pptr = (void **)pp_private_data; + im_entry->private_ptr = talloc_move(im_entry, pptr); + } + + DLIST_ADD(tp->im_list, im_entry); + + /* And notify the dest_ev_ctx to wake up. */ + c = '\0'; + do { + written = write(tp->write_fd, &c, 1); + } while (written == -1 && errno == EINTR); + + end: + + ret = pthread_mutex_unlock(&tp->mutex); + if (ret != 0) { + abort(); + /* Notreached. */ + } +} +#else +/* !HAVE_PTHREAD */ +struct tevent_thread_proxy *tevent_thread_proxy_create( + struct tevent_context *dest_ev_ctx) +{ + errno = ENOSYS; + return NULL; +} + +void tevent_thread_proxy_schedule(struct tevent_thread_proxy *tp, + struct tevent_immediate **pp_im, + tevent_immediate_handler_t handler, + void *pp_private_data) +{ + ; +} +#endif + +static int tevent_threaded_context_destructor( + struct tevent_threaded_context *tctx) +{ + struct tevent_context *main_ev = tevent_wrapper_main_ev(tctx->event_ctx); + int ret; + + if (main_ev != NULL) { + DLIST_REMOVE(main_ev->threaded_contexts, tctx); + } + + /* + * We have to coordinate with _tevent_threaded_schedule_immediate's + * unlock of the event_ctx_mutex. We're in the main thread here, + * and we can be scheduled before the helper thread finalizes its + * call _tevent_threaded_schedule_immediate. This means we would + * pthreadpool_destroy a locked mutex, which is illegal. + */ + ret = pthread_mutex_lock(&tctx->event_ctx_mutex); + if (ret != 0) { + abort(); + } + + ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); + if (ret != 0) { + abort(); + } + + ret = pthread_mutex_destroy(&tctx->event_ctx_mutex); + if (ret != 0) { + abort(); + } + + return 0; +} + +struct tevent_threaded_context *tevent_threaded_context_create( + TALLOC_CTX *mem_ctx, struct tevent_context *ev) +{ +#ifdef HAVE_PTHREAD + struct tevent_context *main_ev = tevent_wrapper_main_ev(ev); + struct tevent_threaded_context *tctx; + int ret; + + ret = tevent_common_wakeup_init(main_ev); + if (ret != 0) { + errno = ret; + return NULL; + } + + tctx = talloc(mem_ctx, struct tevent_threaded_context); + if (tctx == NULL) { + return NULL; + } + tctx->event_ctx = ev; + + ret = pthread_mutex_init(&tctx->event_ctx_mutex, NULL); + if (ret != 0) { + TALLOC_FREE(tctx); + return NULL; + } + + DLIST_ADD(main_ev->threaded_contexts, tctx); + talloc_set_destructor(tctx, tevent_threaded_context_destructor); + + return tctx; +#else + errno = ENOSYS; + return NULL; +#endif +} + +static int tevent_threaded_schedule_immediate_destructor(struct tevent_immediate *im) +{ + if (im->event_ctx != NULL) { + abort(); + } + return 0; +} + +void _tevent_threaded_schedule_immediate(struct tevent_threaded_context *tctx, + struct tevent_immediate *im, + tevent_immediate_handler_t handler, + void *private_data, + const char *handler_name, + const char *location) +{ +#ifdef HAVE_PTHREAD + const char *create_location = im->create_location; + struct tevent_context *main_ev = NULL; + struct tevent_wrapper_glue *glue = NULL; + int ret, wakeup_fd; + + ret = pthread_mutex_lock(&tctx->event_ctx_mutex); + if (ret != 0) { + abort(); + } + + if (tctx->event_ctx == NULL) { + /* + * Our event context is already gone. + */ + ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); + if (ret != 0) { + abort(); + } + return; + } + + glue = tctx->event_ctx->wrapper.glue; + + if ((im->event_ctx != NULL) || (handler == NULL)) { + abort(); + } + if (im->destroyed) { + abort(); + } + if (im->busy) { + abort(); + } + + main_ev = tevent_wrapper_main_ev(tctx->event_ctx); + + *im = (struct tevent_immediate) { + .event_ctx = tctx->event_ctx, + .wrapper = glue, + .handler = handler, + .private_data = private_data, + .handler_name = handler_name, + .create_location = create_location, + .schedule_location = location, + }; + + /* + * Make sure the event won't be destroyed while + * it's part of the ev->scheduled_immediates list. + * _tevent_schedule_immediate() will reset the destructor + * in tevent_common_threaded_activate_immediate(). + */ + talloc_set_destructor(im, tevent_threaded_schedule_immediate_destructor); + + ret = pthread_mutex_lock(&main_ev->scheduled_mutex); + if (ret != 0) { + abort(); + } + + DLIST_ADD_END(main_ev->scheduled_immediates, im); + wakeup_fd = main_ev->wakeup_fd; + + ret = pthread_mutex_unlock(&main_ev->scheduled_mutex); + if (ret != 0) { + abort(); + } + + ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); + if (ret != 0) { + abort(); + } + + /* + * We might want to wake up the main thread under the lock. We + * had a slightly similar situation in pthreadpool, changed + * with 1c4284c7395f23. This is not exactly the same, as the + * wakeup is only a last-resort thing in case the main thread + * is sleeping. Doing the wakeup under the lock can easily + * lead to a contended mutex, which is much more expensive + * than a noncontended one. So I'd opt for the lower footprint + * initially. Maybe we have to change that later. + */ + tevent_common_wakeup_fd(wakeup_fd); +#else + /* + * tevent_threaded_context_create() returned NULL with ENOSYS... + */ + abort(); +#endif +} + +void tevent_common_threaded_activate_immediate(struct tevent_context *ev) +{ +#ifdef HAVE_PTHREAD + int ret; + ret = pthread_mutex_lock(&ev->scheduled_mutex); + if (ret != 0) { + abort(); + } + + while (ev->scheduled_immediates != NULL) { + struct tevent_immediate *im = ev->scheduled_immediates; + struct tevent_immediate copy = *im; + + DLIST_REMOVE(ev->scheduled_immediates, im); + + tevent_debug(ev, TEVENT_DEBUG_TRACE, + "Schedule immediate event \"%s\": %p from thread into main\n", + im->handler_name, im); + im->handler_name = NULL; + _tevent_schedule_immediate(im, + ev, + copy.handler, + copy.private_data, + copy.handler_name, + copy.schedule_location); + } + + ret = pthread_mutex_unlock(&ev->scheduled_mutex); + if (ret != 0) { + abort(); + } +#else + /* + * tevent_threaded_context_create() returned NULL with ENOSYS... + */ + abort(); +#endif +} diff --git a/lib/tevent/tevent_timed.c b/lib/tevent/tevent_timed.c new file mode 100644 index 0000000..67e39ed --- /dev/null +++ b/lib/tevent/tevent_timed.c @@ -0,0 +1,477 @@ +/* + Unix SMB/CIFS implementation. + + common events code for timed events + + Copyright (C) Andrew Tridgell 2003-2006 + Copyright (C) Stefan Metzmacher 2005-2009 + + ** 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 "replace.h" +#include "system/time.h" +#define TEVENT_DEPRECATED 1 +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +/** + compare two timeval structures. + Return -1 if tv1 < tv2 + Return 0 if tv1 == tv2 + Return 1 if tv1 > tv2 +*/ +int tevent_timeval_compare(const struct timeval *tv1, const struct timeval *tv2) +{ + if (tv1->tv_sec > tv2->tv_sec) return 1; + if (tv1->tv_sec < tv2->tv_sec) return -1; + if (tv1->tv_usec > tv2->tv_usec) return 1; + if (tv1->tv_usec < tv2->tv_usec) return -1; + return 0; +} + +/** + return a zero timeval +*/ +struct timeval tevent_timeval_zero(void) +{ + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + return tv; +} + +/** + return a timeval for the current time +*/ +struct timeval tevent_timeval_current(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv; +} + +/** + return a timeval struct with the given elements +*/ +struct timeval tevent_timeval_set(uint32_t secs, uint32_t usecs) +{ + struct timeval tv; + tv.tv_sec = secs; + tv.tv_usec = usecs; + return tv; +} + +/** + return the difference between two timevals as a timeval + if tv1 comes after tv2, then return a zero timeval + (this is *tv2 - *tv1) +*/ +struct timeval tevent_timeval_until(const struct timeval *tv1, + const struct timeval *tv2) +{ + struct timeval t; + if (tevent_timeval_compare(tv1, tv2) >= 0) { + return tevent_timeval_zero(); + } + t.tv_sec = tv2->tv_sec - tv1->tv_sec; + if (tv1->tv_usec > tv2->tv_usec) { + t.tv_sec--; + t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec); + } else { + t.tv_usec = tv2->tv_usec - tv1->tv_usec; + } + return t; +} + +/** + return true if a timeval is zero +*/ +bool tevent_timeval_is_zero(const struct timeval *tv) +{ + return tv->tv_sec == 0 && tv->tv_usec == 0; +} + +struct timeval tevent_timeval_add(const struct timeval *tv, uint32_t secs, + uint32_t usecs) +{ + struct timeval tv2 = *tv; + tv2.tv_sec += secs; + tv2.tv_usec += usecs; + tv2.tv_sec += tv2.tv_usec / 1000000; + tv2.tv_usec = tv2.tv_usec % 1000000; + + return tv2; +} + +/** + return a timeval in the future with a specified offset +*/ +struct timeval tevent_timeval_current_ofs(uint32_t secs, uint32_t usecs) +{ + struct timeval tv = tevent_timeval_current(); + return tevent_timeval_add(&tv, secs, usecs); +} + +/* + destroy a timed event +*/ +static int tevent_common_timed_destructor(struct tevent_timer *te) +{ + if (te->destroyed) { + tevent_common_check_double_free(te, "tevent_timer double free"); + goto done; + } + te->destroyed = true; + + 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->last_zero_timer == te) { + te->event_ctx->last_zero_timer = DLIST_PREV(te); + } + + tevent_trace_timer_callback(te->event_ctx, te, TEVENT_EVENT_TRACE_DETACH); + DLIST_REMOVE(te->event_ctx->timer_events, te); + + te->event_ctx = NULL; +done: + if (te->busy) { + return -1; + } + te->wrapper = NULL; + + return 0; +} + +static void tevent_common_insert_timer(struct tevent_context *ev, + struct tevent_timer *te, + bool optimize_zero) +{ + struct tevent_timer *prev_te = NULL; + + if (te->destroyed) { + tevent_abort(ev, "tevent_timer use after free"); + return; + } + + /* keep the list ordered */ + 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 { + struct tevent_timer *cur_te; + + /* + * 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; + } + + prev_te = cur_te; + } + + tevent_trace_timer_callback(te->event_ctx, te, TEVENT_EVENT_TRACE_ATTACH); + DLIST_ADD_AFTER(ev->timer_events, te, prev_te); +} + +/* + add a timed event + return NULL on failure (memory allocation error) +*/ +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; + + te = talloc(mem_ctx?mem_ctx:ev, struct tevent_timer); + if (te == NULL) return NULL; + + *te = (struct tevent_timer) { + .event_ctx = ev, + .next_event = next_event, + .handler = handler, + .private_data = private_data, + .handler_name = handler_name, + .location = location, + }; + + if (ev->timer_events == NULL) { + ev->last_zero_timer = NULL; + } + + tevent_common_insert_timer(ev, te, optimize_zero); + + talloc_set_destructor(te, tevent_common_timed_destructor); + + + tevent_debug(ev, TEVENT_DEBUG_TRACE, + "Added timed event \"%s\": %p\n", + handler_name, te); + 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); +} + +void tevent_update_timer(struct tevent_timer *te, struct timeval next_event) +{ + struct tevent_context *ev = te->event_ctx; + + if (ev->last_zero_timer == te) { + te->event_ctx->last_zero_timer = DLIST_PREV(te); + } + tevent_trace_timer_callback(te->event_ctx, te, TEVENT_EVENT_TRACE_DETACH); + DLIST_REMOVE(ev->timer_events, te); + + te->next_event = next_event; + + /* + * Not doing the zero_timer optimization. This is for new code + * that should know about immediates. + */ + tevent_common_insert_timer(ev, te, false); +} + +int tevent_common_invoke_timer_handler(struct tevent_timer *te, + struct timeval current_time, + bool *removed) +{ + struct tevent_context *handler_ev = te->event_ctx; + + if (removed != NULL) { + *removed = false; + } + + if (te->event_ctx == NULL) { + return 0; + } + + /* + * 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 (te->event_ctx->last_zero_timer == te) { + te->event_ctx->last_zero_timer = DLIST_PREV(te); + } + DLIST_REMOVE(te->event_ctx->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 + * overhead of gettimeofday() calls. + * + * otherwise we pass the current time + */ + te->busy = true; + if (te->wrapper != NULL) { + handler_ev = te->wrapper->wrap_ev; + + tevent_wrapper_push_use_internal(handler_ev, te->wrapper); + te->wrapper->ops->before_timer_handler( + te->wrapper->wrap_ev, + te->wrapper->private_state, + te->wrapper->main_ev, + te, + te->next_event, + current_time, + te->handler_name, + te->location); + } + tevent_trace_timer_callback(te->event_ctx, te, TEVENT_EVENT_TRACE_BEFORE_HANDLER); + te->handler(handler_ev, te, current_time, te->private_data); + if (te->wrapper != NULL) { + te->wrapper->ops->after_timer_handler( + te->wrapper->wrap_ev, + te->wrapper->private_state, + te->wrapper->main_ev, + te, + te->next_event, + current_time, + te->handler_name, + te->location); + tevent_wrapper_pop_use_internal(handler_ev, te->wrapper); + } + te->busy = false; + + tevent_debug(te->event_ctx, TEVENT_DEBUG_TRACE, + "Ending timer event %p \"%s\"\n", + te, te->handler_name); + + /* The callback was already called when freed from the handler. */ + if (!te->destroyed) { + tevent_trace_timer_callback(te->event_ctx, te, TEVENT_EVENT_TRACE_DETACH); + } + + te->wrapper = NULL; + te->event_ctx = NULL; + talloc_set_destructor(te, NULL); + TALLOC_FREE(te); + + if (removed != NULL) { + *removed = true; + } + + return 0; +} +/* + do a single event loop using the events defined in ev + + return the delay until the next timed event, + or zero if a timed event was triggered +*/ +struct timeval tevent_common_loop_timer_delay(struct tevent_context *ev) +{ + struct timeval current_time = tevent_timeval_zero(); + struct tevent_timer *te = ev->timer_events; + int ret; + + if (!te) { + /* have a default tick time of 30 seconds. This guarantees + that code that uses its own timeout checking will be + able to proceed eventually */ + return tevent_timeval_set(30, 0); + } + + /* + * work out the right timeout for the next timed event + * + * avoid the syscall to gettimeofday() if the timed event should + * be triggered directly + * + * if there's a delay till the next timed event, we're done + * with just returning the delay + */ + if (!tevent_timeval_is_zero(&te->next_event)) { + struct timeval delay; + + current_time = tevent_timeval_current(); + + delay = tevent_timeval_until(¤t_time, &te->next_event); + if (!tevent_timeval_is_zero(&delay)) { + return delay; + } + } + + /* + * ok, we have a timed event that we'll process ... + */ + ret = tevent_common_invoke_timer_handler(te, current_time, NULL); + if (ret != 0) { + tevent_abort(ev, "tevent_common_invoke_timer_handler() failed"); + } + + return tevent_timeval_zero(); +} + +void tevent_timer_set_tag(struct tevent_timer *te, uint64_t tag) +{ + if (te == NULL) { + return; + } + + te->tag = tag; +} + +uint64_t tevent_timer_get_tag(const struct tevent_timer *te) +{ + if (te == NULL) { + return 0; + } + + return te->tag; +} diff --git a/lib/tevent/tevent_util.c b/lib/tevent/tevent_util.c new file mode 100644 index 0000000..7519e11 --- /dev/null +++ b/lib/tevent/tevent_util.c @@ -0,0 +1,77 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 2005 + Copyright (C) Jelmer Vernooij 2005 + + ** 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 "replace.h" +#include "talloc.h" +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" +#include <fcntl.h> + +/** + Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, + else + if SYSV use O_NDELAY + if BSD use FNDELAY +**/ + +int ev_set_blocking(int fd, bool set) +{ + int val; +#ifdef O_NONBLOCK +#define FLAG_TO_SET O_NONBLOCK +#else +#ifdef SYSV +#define FLAG_TO_SET O_NDELAY +#else /* BSD */ +#define FLAG_TO_SET FNDELAY +#endif +#endif + + if((val = fcntl(fd, F_GETFL, 0)) == -1) + return -1; + if(set) /* Turn blocking on - ie. clear nonblock flag */ + val &= ~FLAG_TO_SET; + else + val |= FLAG_TO_SET; + return fcntl( fd, F_SETFL, val); +#undef FLAG_TO_SET +} + +bool ev_set_close_on_exec(int fd) +{ +#ifdef FD_CLOEXEC + int val; + + val = fcntl(fd, F_GETFD, 0); + if (val >= 0) { + val |= FD_CLOEXEC; + val = fcntl(fd, F_SETFD, val); + if (val != -1) { + return true; + } + } +#endif + return false; +} diff --git a/lib/tevent/tevent_util.h b/lib/tevent/tevent_util.h new file mode 100644 index 0000000..128c231 --- /dev/null +++ b/lib/tevent/tevent_util.h @@ -0,0 +1,183 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 1998-2010 + Copyright (C) Jelmer Vernooij 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* To use these macros you must have a structure containing a next and + prev pointer */ + +#ifndef _DLINKLIST_H +#define _DLINKLIST_H + +/* + February 2010 - changed list format to have a prev pointer from the + list head. This makes DLIST_ADD_END() O(1) even though we only have + one list pointer. + + The scheme is as follows: + + 1) with no entries in the list: + list_head == NULL + + 2) with 1 entry in the list: + list_head->next == NULL + list_head->prev == list_head + + 3) with 2 entries in the list: + list_head->next == element2 + list_head->prev == element2 + element2->prev == list_head + element2->next == NULL + + 4) with N entries in the list: + list_head->next == element2 + list_head->prev == elementN + elementN->prev == element{N-1} + elementN->next == NULL + + This allows us to find the tail of the list by using + list_head->prev, which means we can add to the end of the list in + O(1) time + */ + + +/* + add an element at the front of a list +*/ +#define DLIST_ADD(list, p) \ +do { \ + if (!(list)) { \ + (p)->prev = (list) = (p); \ + (p)->next = NULL; \ + } else { \ + (p)->prev = (list)->prev; \ + (list)->prev = (p); \ + (p)->next = (list); \ + (list) = (p); \ + } \ +} while (0) + +/* + remove an element from a list + Note that the element doesn't have to be in the list. If it + isn't then this is a no-op +*/ +#define DLIST_REMOVE(list, p) \ +do { \ + if ((p) == (list)) { \ + if ((p)->next) (p)->next->prev = (p)->prev; \ + (list) = (p)->next; \ + } else if ((p)->prev && (list) && (p) == (list)->prev) { \ + (p)->prev->next = NULL; \ + (list)->prev = (p)->prev; \ + } else { \ + if ((p)->prev) (p)->prev->next = (p)->next; \ + if ((p)->next) (p)->next->prev = (p)->prev; \ + } \ + if ((p) != (list)) (p)->next = (p)->prev = NULL; \ +} while (0) + +/* + find the head of the list given any element in it. + Note that this costs O(N), so you should avoid this macro + if at all possible! +*/ +#define DLIST_HEAD(p, result_head) \ +do { \ + (result_head) = (p); \ + while (DLIST_PREV(result_head)) (result_head) = (result_head)->prev; \ +} while(0) + +/* return the last element in the list */ +#define DLIST_TAIL(list) ((list)?(list)->prev:NULL) + +/* return the previous element in the list. */ +#define DLIST_PREV(p) (((p)->prev && (p)->prev->next != NULL)?(p)->prev:NULL) + +/* insert 'p' after the given element 'el' in a list. If el is NULL then + this is the same as a DLIST_ADD() */ +#define DLIST_ADD_AFTER(list, p, el) \ +do { \ + if (!(list) || !(el)) { \ + DLIST_ADD(list, p); \ + } else { \ + (p)->prev = (el); \ + (p)->next = (el)->next; \ + (el)->next = (p); \ + if ((p)->next) (p)->next->prev = (p); \ + if ((list)->prev == (el)) (list)->prev = (p); \ + }\ +} while (0) + + +/* + add to the end of a list. +*/ +#define DLIST_ADD_END(list, p) \ +do { \ + if (!(list)) { \ + DLIST_ADD(list, p); \ + } else { \ + DLIST_ADD_AFTER(list, p, (list)->prev); \ + } \ +} while (0) + +/* promote an element to the front of a list */ +#define DLIST_PROMOTE(list, p) \ +do { \ + DLIST_REMOVE(list, p); \ + DLIST_ADD(list, p); \ +} while (0) + +/* + demote an element to the end of a list. +*/ +#define DLIST_DEMOTE(list, p) \ +do { \ + DLIST_REMOVE(list, p); \ + DLIST_ADD_END(list, p); \ +} while (0) + +/* + concatenate two lists - putting all elements of the 2nd list at the + end of the first list. +*/ +#define DLIST_CONCATENATE(list1, list2) \ +do { \ + if (!(list1)) { \ + (list1) = (list2); \ + } else { \ + (list1)->prev->next = (list2); \ + if (list2) { \ + void *_tmplist = (void *)(list1)->prev; \ + (list1)->prev = (list2)->prev; \ + (list2)->prev = _tmplist; \ + } \ + } \ +} while (0) + +#endif /* _DLINKLIST_H */ + +int ev_set_blocking(int fd, bool set); +bool ev_set_close_on_exec(int fd); + +/* Defined here so we can build against older talloc versions that don't + * have this define yet. */ +#ifndef TALLOC_FREE +#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0) +#endif diff --git a/lib/tevent/tevent_wakeup.c b/lib/tevent/tevent_wakeup.c new file mode 100644 index 0000000..e217f33 --- /dev/null +++ b/lib/tevent/tevent_wakeup.c @@ -0,0 +1,67 @@ +/* + Unix SMB/CIFS implementation. + Infrastructure for async requests + Copyright (C) Volker Lendecke 2008 + Copyright (C) Stefan Metzmacher 2009 + + ** 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 "replace.h" +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +struct tevent_wakeup_state { + struct timeval wakeup_time; +}; + +struct tevent_req *tevent_wakeup_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct timeval wakeup_time) +{ + struct tevent_req *req; + struct tevent_wakeup_state *state; + + req = tevent_req_create(mem_ctx, &state, + struct tevent_wakeup_state); + if (!req) { + return NULL; + } + state->wakeup_time = wakeup_time; + + if (!tevent_req_set_endtime(req, ev, wakeup_time)) { + return tevent_req_post(req, ev); + } + return req; +} + +bool tevent_wakeup_recv(struct tevent_req *req) +{ + enum tevent_req_state state; + uint64_t error; + + if (tevent_req_is_error(req, &state, &error)) { + if (state == TEVENT_REQ_TIMED_OUT) { + return true; + } + } + + return false; +} + diff --git a/lib/tevent/tevent_wrapper.c b/lib/tevent/tevent_wrapper.c new file mode 100644 index 0000000..a0e915f --- /dev/null +++ b/lib/tevent/tevent_wrapper.c @@ -0,0 +1,571 @@ +/* + Infrastructure for event context wrappers + + Copyright (C) Stefan Metzmacher 2014 + + ** 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 "replace.h" +#ifdef HAVE_PTHREAD +#include "system/threads.h" +#endif +#define TEVENT_DEPRECATED 1 +#include "tevent.h" +#include "tevent_internal.h" +#include "tevent_util.h" + +static int tevent_wrapper_glue_context_init(struct tevent_context *ev) +{ + tevent_abort(ev, "tevent_wrapper_glue_context_init() called"); + errno = ENOSYS; + return -1; +} + +static struct tevent_fd *tevent_wrapper_glue_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 tevent_wrapper_glue *glue = ev->wrapper.glue; + struct tevent_fd *fde = NULL; + + if (glue->destroyed) { + tevent_abort(ev, "add_fd wrapper use after free"); + return NULL; + } + + if (glue->main_ev == NULL) { + errno = EINVAL; + return NULL; + } + + fde = _tevent_add_fd(glue->main_ev, mem_ctx, fd, flags, + handler, private_data, + handler_name, location); + if (fde == NULL) { + return NULL; + } + + fde->wrapper = glue; + + return fde; +} + +static struct tevent_timer *tevent_wrapper_glue_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) +{ + struct tevent_wrapper_glue *glue = ev->wrapper.glue; + struct tevent_timer *te = NULL; + + if (glue->destroyed) { + tevent_abort(ev, "add_timer wrapper use after free"); + return NULL; + } + + if (glue->main_ev == NULL) { + errno = EINVAL; + return NULL; + } + + te = _tevent_add_timer(glue->main_ev, mem_ctx, next_event, + handler, private_data, + handler_name, location); + if (te == NULL) { + return NULL; + } + + te->wrapper = glue; + + return te; +} + +static void tevent_wrapper_glue_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 tevent_wrapper_glue *glue = ev->wrapper.glue; + + if (glue->destroyed) { + tevent_abort(ev, "scheduke_immediate wrapper use after free"); + return; + } + + if (glue->main_ev == NULL) { + tevent_abort(ev, location); + errno = EINVAL; + return; + } + + _tevent_schedule_immediate(im, glue->main_ev, + handler, private_data, + handler_name, location); + + im->wrapper = glue; + + return; +} + +static struct tevent_signal *tevent_wrapper_glue_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) +{ + struct tevent_wrapper_glue *glue = ev->wrapper.glue; + struct tevent_signal *se = NULL; + + if (glue->destroyed) { + tevent_abort(ev, "add_signal wrapper use after free"); + return NULL; + } + + if (glue->main_ev == NULL) { + errno = EINVAL; + return NULL; + } + + se = _tevent_add_signal(glue->main_ev, mem_ctx, + signum, sa_flags, + handler, private_data, + handler_name, location); + if (se == NULL) { + return NULL; + } + + se->wrapper = glue; + + return se; +} + +static int tevent_wrapper_glue_loop_once(struct tevent_context *ev, const char *location) +{ + tevent_abort(ev, "tevent_wrapper_glue_loop_once() called"); + errno = ENOSYS; + return -1; +} + +static int tevent_wrapper_glue_loop_wait(struct tevent_context *ev, const char *location) +{ + tevent_abort(ev, "tevent_wrapper_glue_loop_wait() called"); + errno = ENOSYS; + return -1; +} + +static const struct tevent_ops tevent_wrapper_glue_ops = { + .context_init = tevent_wrapper_glue_context_init, + .add_fd = tevent_wrapper_glue_add_fd, + .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_wrapper_glue_add_timer, + .schedule_immediate = tevent_wrapper_glue_schedule_immediate, + .add_signal = tevent_wrapper_glue_add_signal, + .loop_once = tevent_wrapper_glue_loop_once, + .loop_wait = tevent_wrapper_glue_loop_wait, +}; + +static int tevent_wrapper_context_destructor(struct tevent_context *wrap_ev) +{ + struct tevent_wrapper_glue *glue = wrap_ev->wrapper.glue; + struct tevent_context *main_ev = NULL; + struct tevent_fd *fd = NULL, *fn = NULL; + struct tevent_timer *te = NULL, *tn = NULL; + struct tevent_immediate *ie = NULL, *in = NULL; + struct tevent_signal *se = NULL, *sn = NULL; +#ifdef HAVE_PTHREAD + struct tevent_threaded_context *tctx = NULL, *tctxn = NULL; +#endif + + if (glue == NULL) { + tevent_abort(wrap_ev, + "tevent_wrapper_context_destructor() active on main"); + /* static checker support, return below is never reached */ + return -1; + } + + if (glue->destroyed && glue->busy) { + tevent_common_check_double_free(wrap_ev, + "tevent_context wrapper double free"); + } + glue->destroyed = true; + + if (glue->busy) { + return -1; + } + + main_ev = glue->main_ev; + if (main_ev == NULL) { + return 0; + } + + tevent_debug(wrap_ev, TEVENT_DEBUG_TRACE, + "Destroying wrapper context %p \"%s\"\n", + wrap_ev, talloc_get_name(glue->private_state)); + + glue->main_ev = NULL; + DLIST_REMOVE(main_ev->wrapper.list, glue); + +#ifdef HAVE_PTHREAD + for (tctx = main_ev->threaded_contexts; tctx != NULL; tctx = tctxn) { + int ret; + + tctxn = tctx->next; + + if (tctx->event_ctx != glue->wrap_ev) { + continue; + } + + ret = pthread_mutex_lock(&tctx->event_ctx_mutex); + if (ret != 0) { + abort(); + } + + /* + * Indicate to the thread that the tevent_context is + * gone. The counterpart of this is in + * _tevent_threaded_schedule_immediate, there we read + * this under the threaded_context's mutex. + */ + + tctx->event_ctx = NULL; + + ret = pthread_mutex_unlock(&tctx->event_ctx_mutex); + if (ret != 0) { + abort(); + } + + DLIST_REMOVE(main_ev->threaded_contexts, tctx); + } +#endif + + for (fd = main_ev->fd_events; fd; fd = fn) { + fn = fd->next; + + if (fd->wrapper != glue) { + continue; + } + + tevent_fd_set_flags(fd, 0); + + fd->wrapper = NULL; + fd->event_ctx = NULL; + DLIST_REMOVE(main_ev->fd_events, fd); + } + + for (te = main_ev->timer_events; te; te = tn) { + tn = te->next; + + if (te->wrapper != glue) { + continue; + } + + te->wrapper = NULL; + te->event_ctx = NULL; + + if (main_ev->last_zero_timer == te) { + main_ev->last_zero_timer = DLIST_PREV(te); + } + DLIST_REMOVE(main_ev->timer_events, te); + } + + for (ie = main_ev->immediate_events; ie; ie = in) { + in = ie->next; + + if (ie->wrapper != glue) { + continue; + } + + ie->wrapper = NULL; + ie->event_ctx = NULL; + ie->cancel_fn = NULL; + DLIST_REMOVE(main_ev->immediate_events, ie); + } + + for (se = main_ev->signal_events; se; se = sn) { + sn = se->next; + + if (se->wrapper != glue) { + continue; + } + + se->wrapper = NULL; + tevent_cleanup_pending_signal_handlers(se); + } + + return 0; +} + +struct tevent_context *_tevent_context_wrapper_create(struct tevent_context *main_ev, + TALLOC_CTX *mem_ctx, + const struct tevent_wrapper_ops *ops, + void *pstate, + size_t psize, + const char *type, + const char *location) +{ + void **ppstate = (void **)pstate; + struct tevent_context *ev = NULL; + + if (main_ev->wrapper.glue != NULL) { + /* + * stacking of wrappers is not supported + */ + tevent_debug(main_ev->wrapper.glue->main_ev, TEVENT_DEBUG_FATAL, + "%s: %s() stacking not allowed\n", + __func__, location); + errno = EINVAL; + return NULL; + } + + if (main_ev->nesting.allowed) { + /* + * wrappers conflict with nesting + */ + tevent_debug(main_ev, TEVENT_DEBUG_FATAL, + "%s: %s() conflicts with nesting\n", + __func__, location); + errno = EINVAL; + return NULL; + } + + ev = talloc_zero(mem_ctx, struct tevent_context); + if (ev == NULL) { + return NULL; + } + ev->ops = &tevent_wrapper_glue_ops; + + ev->wrapper.glue = talloc_zero(ev, struct tevent_wrapper_glue); + if (ev->wrapper.glue == NULL) { + talloc_free(ev); + return NULL; + } + + talloc_set_destructor(ev, tevent_wrapper_context_destructor); + + ev->wrapper.glue->wrap_ev = ev; + ev->wrapper.glue->main_ev = main_ev; + ev->wrapper.glue->ops = ops; + ev->wrapper.glue->private_state = talloc_zero_size(ev->wrapper.glue, psize); + if (ev->wrapper.glue->private_state == NULL) { + talloc_free(ev); + return NULL; + } + talloc_set_name_const(ev->wrapper.glue->private_state, type); + + DLIST_ADD_END(main_ev->wrapper.list, ev->wrapper.glue); + + *ppstate = ev->wrapper.glue->private_state; + return ev; +} + +bool tevent_context_is_wrapper(struct tevent_context *ev) +{ + if (ev->wrapper.glue != NULL) { + return true; + } + + return false; +} + +_PRIVATE_ +struct tevent_context *tevent_wrapper_main_ev(struct tevent_context *ev) +{ + if (ev == NULL) { + return NULL; + } + + if (ev->wrapper.glue == NULL) { + return ev; + } + + return ev->wrapper.glue->main_ev; +} + +/* + * 32 stack elements should be more than enough + * + * e.g. Samba uses just 8 elements for [un]become_{root,user}() + */ +#define TEVENT_WRAPPER_STACK_SIZE 32 + +static struct tevent_wrapper_stack { + const void *ev_ptr; + const struct tevent_wrapper_glue *wrapper; +} wrapper_stack[TEVENT_WRAPPER_STACK_SIZE]; + +static size_t wrapper_stack_idx; + +_PRIVATE_ +void tevent_wrapper_push_use_internal(struct tevent_context *ev, + struct tevent_wrapper_glue *wrapper) +{ + /* + * ev and wrapper need to belong together! + * It's also fine to only have a raw ev + * without a wrapper. + */ + if (unlikely(ev->wrapper.glue != wrapper)) { + tevent_abort(ev, "tevent_wrapper_push_use_internal() invalid arguments"); + return; + } + + if (wrapper != NULL) { + if (unlikely(wrapper->busy)) { + tevent_abort(ev, "wrapper already busy!"); + return; + } + wrapper->busy = true; + } + + if (unlikely(wrapper_stack_idx >= TEVENT_WRAPPER_STACK_SIZE)) { + tevent_abort(ev, "TEVENT_WRAPPER_STACK_SIZE overflow"); + return; + } + + wrapper_stack[wrapper_stack_idx] = (struct tevent_wrapper_stack) { + .ev_ptr = ev, + .wrapper = wrapper, + }; + wrapper_stack_idx++; +} + +_PRIVATE_ +void tevent_wrapper_pop_use_internal(const struct tevent_context *__ev_ptr, + struct tevent_wrapper_glue *wrapper) +{ + struct tevent_context *main_ev = NULL; + + /* + * Note that __ev_ptr might a a stale pointer and should not + * be touched, we just compare the pointer value in order + * to enforce the stack order. + */ + + if (wrapper != NULL) { + main_ev = wrapper->main_ev; + } + + if (unlikely(wrapper_stack_idx == 0)) { + tevent_abort(main_ev, "tevent_wrapper stack already empty"); + return; + } + wrapper_stack_idx--; + + if (wrapper != NULL) { + wrapper->busy = false; + } + + if (wrapper_stack[wrapper_stack_idx].ev_ptr != __ev_ptr) { + tevent_abort(main_ev, "tevent_wrapper_pop_use mismatch ev!"); + return; + } + if (wrapper_stack[wrapper_stack_idx].wrapper != wrapper) { + tevent_abort(main_ev, "tevent_wrapper_pop_use mismatch wrap!"); + return; + } + + if (wrapper == NULL) { + return; + } + + if (wrapper->destroyed) { + /* + * Notice that we can't use TALLOC_FREE() + * here because wrapper is a talloc child + * of wrapper->wrap_ev. + */ + talloc_free(wrapper->wrap_ev); + } +} + +bool _tevent_context_push_use(struct tevent_context *ev, + const char *location) +{ + bool ok; + + if (ev->wrapper.glue == NULL) { + tevent_wrapper_push_use_internal(ev, NULL); + return true; + } + + if (ev->wrapper.glue->main_ev == NULL) { + return false; + } + + tevent_wrapper_push_use_internal(ev, ev->wrapper.glue); + ok = ev->wrapper.glue->ops->before_use(ev->wrapper.glue->wrap_ev, + ev->wrapper.glue->private_state, + ev->wrapper.glue->main_ev, + location); + if (!ok) { + tevent_wrapper_pop_use_internal(ev, ev->wrapper.glue); + return false; + } + + return true; +} + +void _tevent_context_pop_use(struct tevent_context *ev, + const char *location) +{ + tevent_wrapper_pop_use_internal(ev, ev->wrapper.glue); + + if (ev->wrapper.glue == NULL) { + return; + } + + if (ev->wrapper.glue->main_ev == NULL) { + return; + } + + ev->wrapper.glue->ops->after_use(ev->wrapper.glue->wrap_ev, + ev->wrapper.glue->private_state, + ev->wrapper.glue->main_ev, + location); +} + +bool tevent_context_same_loop(struct tevent_context *ev1, + struct tevent_context *ev2) +{ + struct tevent_context *main_ev1 = tevent_wrapper_main_ev(ev1); + struct tevent_context *main_ev2 = tevent_wrapper_main_ev(ev2); + + if (main_ev1 == NULL) { + return false; + } + + if (main_ev1 == main_ev2) { + return true; + } + + return false; +} diff --git a/lib/tevent/wscript b/lib/tevent/wscript new file mode 100644 index 0000000..5c6f02c --- /dev/null +++ b/lib/tevent/wscript @@ -0,0 +1,175 @@ +#!/usr/bin/env python + +APPNAME = 'tevent' +VERSION = '0.13.0' + +import sys, os + +# find the buildtools directory +top = '.' +while not os.path.exists(top+'/buildtools') and len(top.split('/')) < 5: + top = top + '/..' +sys.path.insert(0, top + '/buildtools/wafsamba') + +out = 'bin' + +import wafsamba +from wafsamba import samba_dist, samba_utils +from waflib import Options, Logs, Context, Errors + +samba_dist.DIST_DIRS('''lib/tevent:. lib/replace:lib/replace + lib/talloc:lib/talloc buildtools:buildtools + third_party/cmocka:third_party/cmocka + third_party/waf:third_party/waf''') + +def options(opt): + opt.BUILTIN_DEFAULT('replace') + opt.PRIVATE_EXTENSION_DEFAULT('tevent', noextension='tevent') + opt.RECURSE('lib/replace') + opt.RECURSE('lib/talloc') + + +def configure(conf): + conf.RECURSE('lib/replace') + conf.RECURSE('lib/talloc') + + if conf.CHECK_FOR_THIRD_PARTY(): + conf.RECURSE('third_party/cmocka') + else: + if not conf.CHECK_CMOCKA(): + raise Errors.WafError('cmocka development package have not been found.\nIf third_party is installed, check that it is in the proper place.') + else: + conf.define('USING_SYSTEM_CMOCKA', 1) + + 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 not conf.env.disable_python and \ + 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.SAMBA_CHECK_PYTHON() + conf.SAMBA_CHECK_PYTHON_HEADERS() + + conf.SAMBA_CONFIG_H() + + conf.SAMBA_CHECK_UNDEFINED_SYMBOL_FLAGS() + +def build(bld): + bld.RECURSE('lib/replace') + bld.RECURSE('lib/talloc') + + if bld.CHECK_FOR_THIRD_PARTY(): + bld.RECURSE('third_party/cmocka') + + SRC = '''tevent.c tevent_debug.c tevent_fd.c tevent_immediate.c + tevent_queue.c tevent_req.c tevent_wrapper.c + tevent_poll.c tevent_threads.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.CONFIG_SET('HAVE_SOLARIS_PORTS'): + SRC += ' tevent_port.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'): + tevent_deps = 'replace talloc' + if bld.CONFIG_SET('HAVE_PTHREAD'): + tevent_deps += ' pthread' + + bld.SAMBA_LIBRARY('tevent', + SRC, + deps=tevent_deps, + enabled= not bld.CONFIG_SET('USING_SYSTEM_TEVENT'), + includes='.', + abi_directory='ABI', + abi_match='tevent_* _tevent_*', + vnum=VERSION, + public_headers=('' if private_library else '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('_tevent', + 'pytevent.c', + deps='tevent', + realname='_tevent.so', + cflags='-DPACKAGE_VERSION=\"%s\"' % VERSION) + + + bld.INSTALL_WILDCARD('${PYTHONARCHDIR}', 'tevent.py', flat=False) + + # install out various python scripts for use by make test + bld.SAMBA_SCRIPT('tevent_python', + pattern='tevent.py', + installdir='python') + + bld.SAMBA_BINARY('test_tevent_tag', + source='tests/test_tevent_tag.c', + deps='cmocka tevent', + install=False) + + bld.SAMBA_BINARY('test_tevent_trace', + source='tests/test_tevent_trace.c', + deps='cmocka tevent', + install=False) + +def test(ctx): + '''test tevent''' + print("The tevent testsuite is part of smbtorture in samba4") + + samba_utils.ADD_LD_LIBRARY_PATH('bin/shared') + samba_utils.ADD_LD_LIBRARY_PATH('bin/shared/private') + + pyret = samba_utils.RUN_PYTHON_TESTS(['bindings.py']) + + unit_test_ret = 0 + unit_tests = [ + 'test_tevent_tag', + 'test_tevent_trace', + ] + + for unit_test in unit_tests: + unit_test_cmd = os.path.join(Context.g_module.out, unit_test) + unit_test_ret = unit_test_ret or samba_utils.RUN_COMMAND(unit_test_cmd) + + sys.exit(pyret or unit_test_ret) + +def dist(): + '''makes a tarball for distribution''' + samba_dist.dist() + +def reconfigure(ctx): + '''reconfigure if config scripts have changed''' + samba_utils.reconfigure(ctx) |