From 6903c6909acaffd896baf56f08ca1869c83dab97 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Mon, 8 Jul 2013 15:11:25 +0200 Subject: [PATCH 01/55] tevent: document tevent_req_create state zeroing Signed-off-by: David Disseldorp Reviewed-by: Volker Lendecke Autobuild-User(master): Volker Lendecke Autobuild-Date(master): Mon Jul 8 20:43:49 CEST 2013 on sn-devel-104 (cherry picked from commit e6f79b94891c3fe432739a479fde753002500938) --- lib/tevent/tevent.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index 6b4d371..2bc4e2d 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -919,9 +919,9 @@ bool _tevent_req_cancel(struct tevent_req *req, const char *location); * req = tevent_req_create(mem_ctx, &state, struct computation_state); * @endcode * - * Tevent_req_create() creates 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 + * 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. -- 1.9.1 From d58205f913e30b705ad2f1b30cf89c095046f293 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jul 2013 11:31:57 +0200 Subject: [PATCH 02/55] tevent: Remove the signal pipe if no signal events are around It makes adding/removing the first/last sigevents a bit more expensive, but it will fix tevent_loop_wait not finishing when one signal event was added and removed. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10012 Signed-off-by: Volker Lendecke Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider (cherry picked from commit 066a642f10cae7980eefb2d8ada3a6c3f5220542) --- lib/tevent/tevent_signal.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/tevent/tevent_signal.c b/lib/tevent/tevent_signal.c index 95a099d..fd321ff 100644 --- a/lib/tevent/tevent_signal.c +++ b/lib/tevent/tevent_signal.c @@ -181,7 +181,19 @@ static int tevent_signal_destructor(struct tevent_signal *se) struct tevent_common_signal_list); if (se->event_ctx) { - DLIST_REMOVE(se->event_ctx->signal_events, se); + struct tevent_context *ev = se->event_ctx; + + DLIST_REMOVE(ev->signal_events, se); + + if (ev->signal_events == NULL && ev->pipe_fde != NULL) { + /* + * This was the last signal. Destroy the pipe. + */ + TALLOC_FREE(ev->pipe_fde); + + close(ev->pipe_fds[0]); + close(ev->pipe_fds[1]); + } } talloc_free(sl); -- 1.9.1 From 5996b885e2d748c6d8e4d1f0d2f5ae195866ebd5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 1 Aug 2013 13:13:04 +0200 Subject: [PATCH 03/55] tevent: change version to 0.9.19 * Fix tevent testsuite issue on Solaris. * Add tevent tuturial and documentation updates * Fix Coverity ID 989236 Operands don't affect result * Bug: https://bugzilla.samba.org/show_bug.cgi?id=10012 Signed-off-by: Stefan Metzmacher Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Thu Aug 1 17:05:02 CEST 2013 on sn-devel-104 (cherry picked from commit 8f98f5d85ae30361f6bb9f6f42d6a7fd279301e1) --- lib/tevent/ABI/tevent-0.9.19.sigs | 83 +++++++++++++++++++++++++++++++++++++++ lib/tevent/wscript | 2 +- 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 lib/tevent/ABI/tevent-0.9.19.sigs 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/wscript b/lib/tevent/wscript index 02bddb8..39f2ae4 100755 --- a/lib/tevent/wscript +++ b/lib/tevent/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'tevent' -VERSION = '0.9.18' +VERSION = '0.9.19' blddir = 'bin' -- 1.9.1 From 45c5c977e4151c85b4085474d421c4ae60fe7d73 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 23 Jul 2013 10:08:38 +0200 Subject: [PATCH 04/55] tevent: Add echo server sample code This is under a deliberately permissive license. I would like people to start using libtevent and tevent_req (LGPL) without any worries about where to start from. Signed-off-by: Volker Lendecke Reviewed-by: Amitay Isaacs Autobuild-User(master): Amitay Isaacs Autobuild-Date(master): Mon Aug 5 04:07:58 CEST 2013 on sn-devel-104 (cherry picked from commit cae48e9a36d7e37ec18791439b30a876bde0c775) --- lib/tevent/echo_server.c | 664 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 664 insertions(+) create mode 100644 lib/tevent/echo_server.c diff --git a/lib/tevent/echo_server.c b/lib/tevent/echo_server.c new file mode 100644 index 0000000..a1da0d8 --- /dev/null +++ b/lib/tevent/echo_server.c @@ -0,0 +1,664 @@ +/** + ** 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 +#include +#include +#include +#include +#include +#include +#include +#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 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, &state->addr, &state->addrlen); + if (ret == -1) { + tevent_req_error(req, errno); + return; + } + 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) { + *paddr = state->addr; + } + 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 \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); + } + + memset(&addr, 0, sizeof(addr)); + + addr.sin_family = AF_INET; + addr.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; +} -- 1.9.1 From f214ead72de83249214621c964a55ebabad776c4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 30 Jul 2013 14:37:16 +0200 Subject: [PATCH 05/55] tevent: Fix tutorial reference Signed-off-by: Volker Lendecke Reviewed-by: Andrew Bartlett Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Mon Aug 12 09:17:10 CEST 2013 on sn-devel-104 (cherry picked from commit 6a081e991923b7d089be4a5cdb1a351c2e863db1) --- lib/tevent/doc/tevent_request.dox | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/tevent/doc/tevent_request.dox b/lib/tevent/doc/tevent_request.dox index 3358cfb..7fcfb55 100644 --- a/lib/tevent/doc/tevent_request.dox +++ b/lib/tevent/doc/tevent_request.dox @@ -182,10 +182,8 @@ tevent_wakeup_recv() ) @image html tevent_subrequest.png -Comprehensive example containing features from this chapter is especially by -reason of nested subrequests very long and therefore it is located as an -example on the attached CD. Description and explanation is placed within the -source code itself (subrequest.c) and enclosed file README. The example is -available here. +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. */ -- 1.9.1 From 8004b1ed2c89361657c5fc4d55dbd8af7b1f0b7e Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 16 Aug 2013 11:32:08 +0000 Subject: [PATCH 06/55] tevent: Remove a pointless goto Signed-off-by: Volker Lendecke Reviewed-by: Michael Adam (cherry picked from commit 6c0758219a8d3dc0c6673f8c7b38386dbbc75559) --- lib/tevent/tevent_wakeup.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/tevent/tevent_wakeup.c b/lib/tevent/tevent_wakeup.c index 82c3942..e217f33 100644 --- a/lib/tevent/tevent_wakeup.c +++ b/lib/tevent/tevent_wakeup.c @@ -46,12 +46,9 @@ struct tevent_req *tevent_wakeup_send(TALLOC_CTX *mem_ctx, state->wakeup_time = wakeup_time; if (!tevent_req_set_endtime(req, ev, wakeup_time)) { - goto post; + return tevent_req_post(req, ev); } - return req; -post: - return tevent_req_post(req, ev); } bool tevent_wakeup_recv(struct tevent_req *req) -- 1.9.1 From c77574adaf759b84f6defafd8f427d872507a3cf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 6 Sep 2013 15:37:56 -0700 Subject: [PATCH 07/55] tevent: Use talloc_pooled_object for tevent_req_create Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison Autobuild-User(master): Volker Lendecke Autobuild-Date(master): Sun Sep 8 13:39:25 CEST 2013 on sn-devel-104 (cherry picked from commit 8f4069c7cd10a143286c7a32c1b612380afd7c72) --- lib/tevent/tevent_req.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c index d8d0c5f..556d984 100644 --- a/lib/tevent/tevent_req.c +++ b/lib/tevent/tevent_req.c @@ -61,10 +61,13 @@ struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, void **ppdata = (void **)pdata; void *data; - req = talloc_zero(mem_ctx, struct tevent_req); + req = talloc_pooled_object( + mem_ctx, struct tevent_req, 2, + sizeof(struct tevent_immediate) + data_size); if (req == NULL) { return NULL; } + ZERO_STRUCTP(req); req->internal.private_type = type; req->internal.create_location = location; req->internal.finish_location = NULL; -- 1.9.1 From 3c7b4a2fcae43086a6ec7e5b6c6f85c91d1cddbf Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 17 Sep 2011 19:53:55 +0200 Subject: [PATCH 08/55] tevent: cancel the timeout timer when the request is finished As we might defer the callback with tevent_req_defer_callback() when calling tevent_req_done(), we should cancel the timeout directly. Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 577afba8b3b75d8ebf8bc496802974b834a53f83) --- lib/tevent/tevent_req.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c index 556d984..4a3b8b1 100644 --- a/lib/tevent/tevent_req.c +++ b/lib/tevent/tevent_req.c @@ -109,6 +109,12 @@ static void tevent_req_finish(struct tevent_req *req, enum tevent_req_state state, const char *location) { + /* + * make sure we do not timeout after + * the request was already finished + */ + TALLOC_FREE(req->internal.timer); + req->internal.state = state; _tevent_req_notify_callback(req, location); } -- 1.9.1 From a4467815bf441e915146f86ffd65b9a9101cfcef Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 27 Sep 2013 02:59:22 +0200 Subject: [PATCH 09/55] tevent: let tevent_req_received() clear the private_cancel function This makes sure it's not called when the private state is already gone. Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 39888fd4a3960f3f6a52aad76507faf030888d57) --- lib/tevent/tevent_req.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c index 4a3b8b1..a324418 100644 --- a/lib/tevent/tevent_req.c +++ b/lib/tevent/tevent_req.c @@ -203,6 +203,7 @@ void tevent_req_received(struct tevent_req *req) { TALLOC_FREE(req->data); req->private_print = NULL; + req->private_cancel = NULL; TALLOC_FREE(req->internal.trigger); TALLOC_FREE(req->internal.timer); -- 1.9.1 From f7cbb57731d35c7ccbd67e99959fcace0a27de43 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 27 Sep 2013 03:02:24 +0200 Subject: [PATCH 10/55] tevent: tevent_req_create() already uses ZERO_STRUCT(req) There's no need to zero individual members. Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 7a97d4c4c36d27e2c0732d70345d1766a4a86e94) --- lib/tevent/tevent_req.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c index a324418..581b818 100644 --- a/lib/tevent/tevent_req.c +++ b/lib/tevent/tevent_req.c @@ -70,14 +70,12 @@ struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, ZERO_STRUCTP(req); req->internal.private_type = type; req->internal.create_location = location; - req->internal.finish_location = NULL; req->internal.state = TEVENT_REQ_IN_PROGRESS; req->internal.trigger = tevent_create_immediate(req); if (!req->internal.trigger) { talloc_free(req); return NULL; } - req->internal.defer_callback_ev = NULL; data = talloc_zero_size(req, data_size); if (data == NULL) { -- 1.9.1 From 747708db9dc153ab83943f225171e8bae76e811f Mon Sep 17 00:00:00 2001 From: Gregor Beck Date: Thu, 19 Sep 2013 15:14:25 +0200 Subject: [PATCH 11/55] tevent: add tevent_queue_wait_send/recv() Pair-Programmed-With: Stefan Metzmacher Signed-off-by: Gregor Beck Signed-off-by: Stefan Metzmacher Reviewed-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 8e44c2f96397a4f8cf945bcc810e3a1776d86a08) --- lib/tevent/tevent.h | 33 ++++++++++++++++++++++++++++++ lib/tevent/tevent_queue.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index 2bc4e2d..0705ff3 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -1592,6 +1592,39 @@ size_t tevent_queue_length(struct tevent_queue *queue); */ 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, diff --git a/lib/tevent/tevent_queue.c b/lib/tevent/tevent_queue.c index eeb922f..ebd7147 100644 --- a/lib/tevent/tevent_queue.c +++ b/lib/tevent/tevent_queue.c @@ -302,3 +302,55 @@ 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_nomem(NULL, 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; +} -- 1.9.1 From b4a677fe16467480af9054db370b0904ef56f6ad Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 5 Dec 2013 08:46:47 +0100 Subject: [PATCH 12/55] tevent: use talloc_get_type_abort() in the documentation examples Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit fb06f0e3d38a0cd2d6a55e93c993763adb7cf278) --- lib/tevent/doc/tevent_events.dox | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tevent/doc/tevent_events.dox b/lib/tevent/doc/tevent_events.dox index 8e350d2..d56af25 100644 --- a/lib/tevent/doc/tevent_events.dox +++ b/lib/tevent/doc/tevent_events.dox @@ -45,7 +45,7 @@ struct state { static void callback(struct tevent_context *ev, struct tevent_timer *tim, struct timeval current_time, void *private_data) { - struct state *data = talloc_get_type(private_data, struct state); + struct state *data = talloc_get_type_abort(private_data, struct state); struct tevent_timer *time_event; struct timeval schedule; @@ -153,7 +153,7 @@ struct info_struct { static void foo(struct tevent_context *ev, struct tevent_immediate *im, void *private_data) { - struct info_struct *data = talloc_get_type(private_data, struct info_struct); + struct info_struct *data = talloc_get_type_abort(private_data, struct info_struct); printf("Data value: %d\n", data->counter); } -- 1.9.1 From c77a80219a66660604f6acd21031871c06e11644 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 5 Dec 2013 08:47:27 +0100 Subject: [PATCH 13/55] tevent: make use of talloc_get_type_abort() in tevent_queue.c Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 982bf3c082893bbf59a76ed0e7f670d8932102b1) --- lib/tevent/tevent_queue.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/tevent/tevent_queue.c b/lib/tevent/tevent_queue.c index ebd7147..9c5d469 100644 --- a/lib/tevent/tevent_queue.c +++ b/lib/tevent/tevent_queue.c @@ -133,8 +133,9 @@ static void tevent_queue_immediate_trigger(struct tevent_context *ev, struct tevent_immediate *im, void *private_data) { - struct tevent_queue *q = talloc_get_type(private_data, - struct tevent_queue); + struct tevent_queue *q = + talloc_get_type_abort(private_data, + struct tevent_queue); if (!q->running) { return; -- 1.9.1 From e719001e6aed8e57f1f86c206470819515415cdc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 5 Dec 2013 08:47:27 +0100 Subject: [PATCH 14/55] tevent: make use of talloc_get_type_abort() in tevent_req.c Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 99910b67d267732ac088d9b2b96cd08d367f2cec) --- lib/tevent/tevent_req.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c index 581b818..edb8550 100644 --- a/lib/tevent/tevent_req.c +++ b/lib/tevent/tevent_req.c @@ -167,8 +167,9 @@ static void tevent_req_trigger(struct tevent_context *ev, struct tevent_immediate *im, void *private_data) { - struct tevent_req *req = talloc_get_type(private_data, - struct tevent_req); + struct tevent_req *req = + talloc_get_type_abort(private_data, + struct tevent_req); tevent_req_finish(req, req->internal.state, req->internal.finish_location); @@ -242,8 +243,9 @@ static void tevent_req_timedout(struct tevent_context *ev, struct timeval now, void *private_data) { - struct tevent_req *req = talloc_get_type(private_data, - struct tevent_req); + struct tevent_req *req = + talloc_get_type_abort(private_data, + struct tevent_req); TALLOC_FREE(req->internal.timer); -- 1.9.1 From b3d8e85c211dd8487e2e83862aeb3d3a18d5bd2b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 5 Dec 2013 08:47:27 +0100 Subject: [PATCH 15/55] tevent: make use of talloc_get_type_abort() in tevent_select.c Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit fbdaf7481b81f021a560e366276c79be6680bce6) --- lib/tevent/tevent_select.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/tevent/tevent_select.c b/lib/tevent/tevent_select.c index bfce246..73f27b7 100644 --- a/lib/tevent/tevent_select.c +++ b/lib/tevent/tevent_select.c @@ -91,8 +91,8 @@ static int select_event_fd_destructor(struct tevent_fd *fde) struct select_event_context *select_ev = NULL; if (ev) { - select_ev = talloc_get_type(ev->additional_data, - struct select_event_context); + select_ev = talloc_get_type_abort(ev->additional_data, + struct select_event_context); if (select_ev->maxfd == fde->fd) { select_ev->maxfd = EVENT_INVALID_MAXFD; @@ -113,8 +113,9 @@ static struct tevent_fd *select_event_add_fd(struct tevent_context *ev, TALLOC_C const char *handler_name, const char *location) { - struct select_event_context *select_ev = talloc_get_type(ev->additional_data, - struct select_event_context); + struct select_event_context *select_ev = + talloc_get_type_abort(ev->additional_data, + struct select_event_context); struct tevent_fd *fde; if (fd < 0 || fd >= FD_SETSIZE) { @@ -236,8 +237,9 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru */ static int select_event_loop_once(struct tevent_context *ev, const char *location) { - struct select_event_context *select_ev = talloc_get_type(ev->additional_data, - struct select_event_context); + struct select_event_context *select_ev = + talloc_get_type_abort(ev->additional_data, + struct select_event_context); struct timeval tval; if (ev->signal_events && -- 1.9.1 From 42ab61a893d6f793b9eff69c769048635400f5ee Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 5 Dec 2013 08:47:27 +0100 Subject: [PATCH 16/55] tevent: make use of talloc_get_type_abort() in tevent_signal.c Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 7bf5e6b181cc4ea23103ac3fc4f183ba183476b6) --- lib/tevent/tevent_signal.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/tevent/tevent_signal.c b/lib/tevent/tevent_signal.c index fd321ff..3f157c4 100644 --- a/lib/tevent/tevent_signal.c +++ b/lib/tevent/tevent_signal.c @@ -176,9 +176,9 @@ static int tevent_common_signal_list_destructor(struct tevent_common_signal_list */ static int tevent_signal_destructor(struct tevent_signal *se) { - struct tevent_common_signal_list *sl; - sl = talloc_get_type(se->additional_data, - struct tevent_common_signal_list); + struct tevent_common_signal_list *sl = + talloc_get_type_abort(se->additional_data, + struct tevent_common_signal_list); if (se->event_ctx) { struct tevent_context *ev = se->event_ctx; @@ -486,9 +486,9 @@ int tevent_common_check_signal(struct tevent_context *ev) void tevent_cleanup_pending_signal_handlers(struct tevent_signal *se) { - struct tevent_common_signal_list *sl; - sl = talloc_get_type(se->additional_data, - struct tevent_common_signal_list); + struct tevent_common_signal_list *sl = + talloc_get_type_abort(se->additional_data, + struct tevent_common_signal_list); tevent_common_signal_list_destructor(sl); -- 1.9.1 From d9e8589914a9af21a8168ddf1753159aed08d5f2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 5 Dec 2013 08:47:27 +0100 Subject: [PATCH 17/55] tevent: make use of talloc_get_type_abort() in tevent_epoll.c Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 4cc02d7c84e6c6a07ecde02fc6792ed041bdbe3a) --- lib/tevent/tevent_epoll.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 599c190..951fa42 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -120,17 +120,10 @@ _PRIVATE_ bool tevent_epoll_set_panic_fallback(struct tevent_context *ev, bool (*panic_fallback)(struct tevent_context *ev, bool replay)) { - struct epoll_event_context *epoll_ev; - - if (ev->additional_data == NULL) { - return false; - } + struct epoll_event_context *epoll_ev = + talloc_get_type_abort(ev->additional_data, + struct epoll_event_context); - epoll_ev = talloc_get_type(ev->additional_data, - struct epoll_event_context); - if (epoll_ev == NULL) { - return false; - } epoll_ev->panic_fallback = panic_fallback; return true; } @@ -843,8 +836,9 @@ static struct tevent_fd *epoll_event_add_fd(struct tevent_context *ev, TALLOC_CT const char *handler_name, const char *location) { - struct epoll_event_context *epoll_ev = talloc_get_type(ev->additional_data, - struct epoll_event_context); + 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; @@ -879,7 +873,8 @@ static void epoll_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags) if (fde->flags == flags) return; ev = fde->event_ctx; - epoll_ev = talloc_get_type(ev->additional_data, struct epoll_event_context); + epoll_ev = talloc_get_type_abort(ev->additional_data, + struct epoll_event_context); fde->flags = flags; @@ -898,8 +893,9 @@ static void epoll_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags) */ static int epoll_event_loop_once(struct tevent_context *ev, const char *location) { - struct epoll_event_context *epoll_ev = talloc_get_type(ev->additional_data, - struct epoll_event_context); + struct epoll_event_context *epoll_ev = + talloc_get_type_abort(ev->additional_data, + struct epoll_event_context); struct timeval tval; bool panic_triggered = false; -- 1.9.1 From 422190d7438d48f0dee73c5f8ed33e243269b743 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 11 Dec 2013 18:58:41 +0100 Subject: [PATCH 18/55] tevent: tevent_epoll_set_panic_fallback() can be a void function There's no case where this could return an error. Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 36345d44c8f5ac614f40a9b5bd4b421ffa6cd49a) --- lib/tevent/tevent_epoll.c | 2 +- lib/tevent/tevent_internal.h | 2 +- lib/tevent/tevent_standard.c | 5 +---- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 951fa42..b0d15c8 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -116,7 +116,7 @@ static int epoll_wait_panic_fallback(struct epoll_event_context *epoll_ev, /* called to set the panic fallback function. */ -_PRIVATE_ bool tevent_epoll_set_panic_fallback(struct tevent_context *ev, +_PRIVATE_ void tevent_epoll_set_panic_fallback(struct tevent_context *ev, bool (*panic_fallback)(struct tevent_context *ev, bool replay)) { diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h index b239e74..df73288 100644 --- a/lib/tevent/tevent_internal.h +++ b/lib/tevent/tevent_internal.h @@ -335,7 +335,7 @@ void tevent_poll_event_add_fd_internal(struct tevent_context *ev, bool tevent_poll_mt_init(void); #ifdef HAVE_EPOLL bool tevent_epoll_init(void); -bool tevent_epoll_set_panic_fallback(struct tevent_context *ev, +void tevent_epoll_set_panic_fallback(struct tevent_context *ev, bool (*panic_fallback)(struct tevent_context *ev, bool replay)); #endif diff --git a/lib/tevent/tevent_standard.c b/lib/tevent/tevent_standard.c index 2584994..785d68d 100644 --- a/lib/tevent/tevent_standard.c +++ b/lib/tevent/tevent_standard.c @@ -206,10 +206,7 @@ static int std_event_context_init(struct tevent_context *ev) goto fallback; } #ifdef HAVE_EPOLL - if (!tevent_epoll_set_panic_fallback(ev, std_fallback_to_poll)) { - TALLOC_FREE(ev->additional_data); - goto fallback; - } + tevent_epoll_set_panic_fallback(ev, std_fallback_to_poll); #endif return ret; -- 1.9.1 From 35eddff534e2b36350e1aa20f5fd7fc197afd8b4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 9 Dec 2013 10:29:45 +0100 Subject: [PATCH 19/55] tevent: change TEVENT_SA_INFO_QUEUE_COUNT from 64 to 256 There are some existing callers which assume the old SA_INFO_QUEUE_COUNT 100 value. 256 should give room for the future. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10214 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit cbb93f5442776fbe9810d242f7fe6759adfe3194) --- lib/tevent/tevent_signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tevent/tevent_signal.c b/lib/tevent/tevent_signal.c index 3f157c4..bc58459 100644 --- a/lib/tevent/tevent_signal.c +++ b/lib/tevent/tevent_signal.c @@ -35,7 +35,7 @@ wrap to work correctly. Thanks to Petr Vandrovec for this. */ -#define TEVENT_SA_INFO_QUEUE_COUNT 64 +#define TEVENT_SA_INFO_QUEUE_COUNT 256 struct tevent_sigcounter { uint32_t count; -- 1.9.1 From 2fa1daefb955b03930eab03090fab65849a408fe Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 9 Dec 2013 10:32:00 +0100 Subject: [PATCH 20/55] tevent: give the user the chance to ask for TEVENT_NUM_SIGNALS and TEVENT_SA_INFO_QUEUE_COUNT This way the caller can change use the supported limits without using hardcoded values. Bug: https://bugzilla.samba.org/show_bug.cgi?id=10214 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 4b330ba0a83e17205c851e83097ec8c1dab02a5c) --- lib/tevent/tevent_signal.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/tevent/tevent_signal.c b/lib/tevent/tevent_signal.c index bc58459..b54da2e 100644 --- a/lib/tevent/tevent_signal.c +++ b/lib/tevent/tevent_signal.c @@ -37,6 +37,16 @@ #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; -- 1.9.1 From e071db52734bb679094e3534092f0e6be1e19776 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 27 Sep 2013 04:06:00 +0200 Subject: [PATCH 21/55] tevent: version 0.9.20 This adds the following new features: - tevent_queue_wait_send/recv() - tevent_num_signals() - tevent_sa_info_queue_count() Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Thu Dec 12 00:39:35 CET 2013 on sn-devel-104 (cherry picked from commit e26736dcc25a204bf21a367462d0c10060bee1ad) --- lib/tevent/ABI/tevent-0.9.20.sigs | 87 +++++++++++++++++++++++++++++++++++++++ lib/tevent/wscript | 2 +- 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 lib/tevent/ABI/tevent-0.9.20.sigs 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/wscript b/lib/tevent/wscript index 39f2ae4..3fc87f5 100755 --- a/lib/tevent/wscript +++ b/lib/tevent/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'tevent' -VERSION = '0.9.19' +VERSION = '0.9.20' blddir = 'bin' -- 1.9.1 From 41614d19244399ae67e831c9a17a82ce2bab3c24 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 15 Dec 2013 20:40:06 +0100 Subject: [PATCH 22/55] tevent: Fix CID 1138326 Unchecked return value For this case we explicitly have added tevent_req_oom Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit 91ef262c633aebd0da8ab7c4b51e2aa9d55b7ddb) --- lib/tevent/tevent_queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tevent/tevent_queue.c b/lib/tevent/tevent_queue.c index 9c5d469..35742e5 100644 --- a/lib/tevent/tevent_queue.c +++ b/lib/tevent/tevent_queue.c @@ -329,7 +329,7 @@ struct tevent_req *tevent_queue_wait_send(TALLOC_CTX *mem_ctx, tevent_queue_wait_trigger, NULL); if (!ok) { - tevent_req_nomem(NULL, req); + tevent_req_oom(req); return tevent_req_post(req, ev); } -- 1.9.1 From 8f9f64e5775beba803a31b1fd46d4617ee0b4101 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 25 Dec 2013 23:20:58 -0500 Subject: [PATCH 23/55] Do not return a value from a void function. Reported by herwin Resolves: https://bugzilla.samba.org/show_bug.cgi?id=10346 Signed-off-by: Simo Sorce Reviewed-by: Jeremy Allison (cherry picked from commit ec499c3d668d0788c64276bf9a0f58ce9a915bd6) --- lib/tevent/tevent_epoll.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index b0d15c8..01fcde6 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -125,7 +125,6 @@ _PRIVATE_ void tevent_epoll_set_panic_fallback(struct tevent_context *ev, struct epoll_event_context); epoll_ev->panic_fallback = panic_fallback; - return true; } /* -- 1.9.1 From 647c87a3b81fca6a409b317452c92d608f6cf8ff Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 13 Dec 2013 11:59:43 +0100 Subject: [PATCH 24/55] tevent: Only build "std_fallback_to_poll" when epoll is around Signed-off-by: Volker Lendecke Reviewed-by: Stefan Metzmacher (cherry picked from commit e7d4b7deda2fac7a7dd86dad84bafcae8085ff80) --- lib/tevent/tevent_standard.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/tevent/tevent_standard.c b/lib/tevent/tevent_standard.c index 785d68d..a050901 100644 --- a/lib/tevent/tevent_standard.c +++ b/lib/tevent/tevent_standard.c @@ -54,6 +54,7 @@ static const struct tevent_ops std_event_ops = { 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); @@ -100,6 +101,7 @@ static bool std_fallback_to_poll(struct tevent_context *ev, bool replay) return true; } +#endif static int std_event_loop_once(struct tevent_context *ev, const char *location) { -- 1.9.1 From bc68dcd58f00cb5e1882c7e2b105fb7de9236b4a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 13 Dec 2013 11:59:04 +0100 Subject: [PATCH 25/55] tevent: Add prototypes ... doxygen docs to be filled in :-) Signed-off-by: Volker Lendecke Reviewed-by: Stefan Metzmacher (cherry picked from commit fd80e544169db5fb86288b7b22da4e98a88f4477) --- lib/tevent/tevent.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index 0705ff3..3f8e081 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -340,6 +340,10 @@ struct tevent_signal *_tevent_add_signal(struct tevent_context *ev, #handler, __location__) #endif +size_t tevent_num_signals(void); + +size_t tevent_sa_info_queue_count(void); + #ifdef DOXYGEN /** * @brief Pass a single time through the mainloop -- 1.9.1 From ccab0c4c74f3b441e5cb090865b387df4ccd80a8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 8 Jan 2014 10:01:56 +0100 Subject: [PATCH 26/55] tevent: add doxygen comments for tevent_num_signals() and tevent_sa_info_queue_count() Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 7502a309e8b817036c1ddc38740c214ae416bf29) --- lib/tevent/tevent.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index 3f8e081..d7d4f19 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -319,6 +319,8 @@ void _tevent_schedule_immediate(struct tevent_immediate *im, * * @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, @@ -340,8 +342,29 @@ struct tevent_signal *_tevent_add_signal(struct tevent_context *ev, #handler, __location__) #endif +/** + * @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 -- 1.9.1 From 0714e66c2241806adbe94d6e8a217df8b0228f4a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 27 Sep 2013 03:41:29 +0200 Subject: [PATCH 27/55] tevent: add/use tevent_req_destructor This makes sure we call tevent_req_received(req) on talloc_free() and cleanup things in a defined order. Note that some callers used their own destructor for their tevent_req instance, they'll just overwrite this, which is not intended, but works without problems. Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 0ed93e099af833045d9d00b9a8faeb5b93b6ef2e) --- lib/tevent/tevent_req.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c index edb8550..30e91e2 100644 --- a/lib/tevent/tevent_req.c +++ b/lib/tevent/tevent_req.c @@ -51,6 +51,8 @@ char *tevent_req_print(TALLOC_CTX *mem_ctx, struct tevent_req *req) 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, @@ -86,10 +88,18 @@ struct tevent_req *_tevent_req_create(TALLOC_CTX *mem_ctx, req->data = data; + talloc_set_destructor(req, tevent_req_destructor); + *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; @@ -200,7 +210,8 @@ bool tevent_req_is_in_progress(struct tevent_req *req) void tevent_req_received(struct tevent_req *req) { - TALLOC_FREE(req->data); + talloc_set_destructor(req, NULL); + req->private_print = NULL; req->private_cancel = NULL; @@ -208,6 +219,8 @@ void tevent_req_received(struct tevent_req *req) TALLOC_FREE(req->internal.timer); req->internal.state = TEVENT_REQ_RECEIVED; + + TALLOC_FREE(req->data); } bool tevent_req_poll(struct tevent_req *req, -- 1.9.1 From 6a00b5906ad935ce06bf4e61cde2fb7fe49899eb Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 27 Sep 2013 02:29:57 +0200 Subject: [PATCH 28/55] tevent: add tevent_req_set_cleanup_fn() Note that some callers used their own destructor for their tevent_req instance, they'll just overwrite this, which is not intended, but works without problems. The intended way is to specify a cleanup function and handle the TEVENT_REQ_RECEIVED state as destructor. Note that the TEVENT_REQ_RECEIVED cleanup event might be triggered by an explicit tevent_req_received() in the _recv() function. The TEVENT_REQ_RECEIVED event is only triggered once as tevent_req_received() will remove the destructor. So the difference compared to a custom destructor is that the struct tevent_req itself can continue to be there, while tevent_req_received() removed all internal state. Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit 50b9f154d22f5c356e66bba341e9ee0292218cfd) --- lib/tevent/tevent.h | 35 +++++++++++++++++++++++++++++++++++ lib/tevent/tevent_internal.h | 12 ++++++++++++ lib/tevent/tevent_req.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index d7d4f19..c54cbe2 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -934,6 +934,41 @@ bool _tevent_req_cancel(struct tevent_req *req, const char *location); _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. diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h index df73288..d25dc05 100644 --- a/lib/tevent/tevent_internal.h +++ b/lib/tevent/tevent_internal.h @@ -74,6 +74,18 @@ struct tevent_req { 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. diff --git a/lib/tevent/tevent_req.c b/lib/tevent/tevent_req.c index 30e91e2..c86fb68 100644 --- a/lib/tevent/tevent_req.c +++ b/lib/tevent/tevent_req.c @@ -113,6 +113,24 @@ void _tevent_req_notify_callback(struct tevent_req *req, const char *location) } } +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) @@ -124,6 +142,10 @@ static void tevent_req_finish(struct tevent_req *req, TALLOC_FREE(req->internal.timer); req->internal.state = state; + req->internal.finish_location = location; + + tevent_req_cleanup(req); + _tevent_req_notify_callback(req, location); } @@ -220,6 +242,8 @@ void tevent_req_received(struct tevent_req *req) req->internal.state = TEVENT_REQ_RECEIVED; + tevent_req_cleanup(req); + TALLOC_FREE(req->data); } @@ -315,3 +339,9 @@ bool _tevent_req_cancel(struct tevent_req *req, const char *location) 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; +} -- 1.9.1 From c115250052987cbb79c5e5344d2bb41e492165f6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 27 Sep 2013 04:06:00 +0200 Subject: [PATCH 29/55] tevent: version 0.9.21 This fixes a the following bugs: - fix a crash bug in tevent_queue_immediate_trigger() - add missing tevent_num_signals() and tevent_sa_info_queue_count() prototypes including documentation. This adds the following new features: - tevent_req_set_cleanup_fn() Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke (cherry picked from commit c4c88d1ee8960ae0d8a392821cf4f218725ab660) --- lib/tevent/ABI/tevent-0.9.21.sigs | 88 +++++++++++++++++++++++++++++++++++++++ lib/tevent/wscript | 2 +- 2 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 lib/tevent/ABI/tevent-0.9.21.sigs 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/wscript b/lib/tevent/wscript index 3fc87f5..bd19780 100755 --- a/lib/tevent/wscript +++ b/lib/tevent/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'tevent' -VERSION = '0.9.20' +VERSION = '0.9.21' blddir = 'bin' -- 1.9.1 From 8e1a47a840d9bd2156a64f11bb93cad9e23d5a8f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 27 Feb 2014 09:08:17 +0100 Subject: [PATCH 30/55] lib/tevent/tests: add missing #include "torture/local/proto.h" Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett (cherry picked from commit 4e5404967ecfd865d8554acfde8fa45c94702eb6) --- lib/tevent/testsuite.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/tevent/testsuite.c b/lib/tevent/testsuite.c index 7851c6c..34d13bb 100644 --- a/lib/tevent/testsuite.c +++ b/lib/tevent/testsuite.c @@ -30,6 +30,7 @@ #include "system/select.h" #include "system/network.h" #include "torture/torture.h" +#include "torture/local/proto.h" #ifdef HAVE_PTHREAD #include #include -- 1.9.1 From 680e44b89ec879228ca7447c9dba43ebfa405195 Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik Date: Fri, 4 Apr 2014 13:27:35 +0200 Subject: [PATCH 31/55] tevent: Update flags in tevent pkgconfig file After exapnding, @LIB_RPATH@ will be -Wl,-rpatch,/usr/local/lib if rpath is used on install. But "-Wl," will be passed to linker and should not be among CFLAGS. Other pkgconfig files have @LIB_RPATH@ in the right place. @see commit 735c1cd2da15167748e92ba6de48fdb5169db587 Signed-off-by: Lukas Slebodnik Reviewed-by: Andrew Bartlett Reviewed-by: Stefan Metzmacher (cherry picked from commit a83c5240b1332d5a97dd21ecd3666a9c2ff38643) --- lib/tevent/tevent.pc.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tevent/tevent.pc.in b/lib/tevent/tevent.pc.in index 1091ff0..eb0e564 100644 --- a/lib/tevent/tevent.pc.in +++ b/lib/tevent/tevent.pc.in @@ -7,6 +7,6 @@ Name: tevent Description: An event system library Version: @PACKAGE_VERSION@ Requires: talloc -Libs: -L${libdir} -ltevent -Cflags: @LIB_RPATH@ -I${includedir} +Libs: @LIB_RPATH@ -L${libdir} -ltevent +Cflags: -I${includedir} URL: http://samba.org/ -- 1.9.1 From aeb9ae4122ff3a8b9606882f46d697f6f1c353ea Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 20 Jun 2014 18:04:13 +0200 Subject: [PATCH 32/55] tevent:build: improve detection of srcdir Signed-off-by: Michael Adam Reviewed-by: Amitay Isaacs (cherry picked from commit befb39441f6919624df475c6495e822e5acc42ff) --- lib/tevent/wscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tevent/wscript b/lib/tevent/wscript index bd19780..8d29e04 100755 --- a/lib/tevent/wscript +++ b/lib/tevent/wscript @@ -10,7 +10,7 @@ import sys, os # find the buildtools directory srcdir = '.' while not os.path.exists(srcdir+'/buildtools') and len(srcdir.split('/')) < 5: - srcdir = '../' + srcdir + srcdir = srcdir + '/..' sys.path.insert(0, srcdir + '/buildtools/wafsamba') import wafsamba, samba_dist, Options, Logs -- 1.9.1 From 1f9dcdf5273a5e321702d08441957169b59bb16c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 14 Sep 2014 20:45:31 +0200 Subject: [PATCH 33/55] lib: Polish echo_server Samba has a lot of struct assignments now, in a lot of cases it simplifies the code. Use it in the sample code. Signed-off-by: Volker Lendecke Reviewed-by: Martin Schwenke Autobuild-User(master): Volker Lendecke Autobuild-Date(master): Thu Sep 18 23:02:38 CEST 2014 on sn-devel-104 --- lib/tevent/echo_server.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/tevent/echo_server.c b/lib/tevent/echo_server.c index a1da0d8..102f7b4 100644 --- a/lib/tevent/echo_server.c +++ b/lib/tevent/echo_server.c @@ -619,10 +619,10 @@ int main(int argc, const char **argv) exit(1); } - memset(&addr, 0, sizeof(addr)); - - addr.sin_family = AF_INET; - addr.sin_port = htons(port); + addr = (struct sockaddr_in) { + .sin_family = AF_INET, + .sin_port = htons(port) + }; ret = bind(listen_sock, (struct sockaddr *)&addr, sizeof(addr)); if (ret == -1) { -- 1.9.1 From 0ed076081f8066eae3bac1cf121c38c33742de9f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 22 Jul 2014 14:54:11 +0200 Subject: [PATCH 34/55] tevent: remove unused exit_code in tevent_poll.c Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 1ea3364721522dcd68fee629b017e72ab35ff6e1) --- lib/tevent/tevent_poll.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/tevent/tevent_poll.c b/lib/tevent/tevent_poll.c index 75d0ced..573ba93 100644 --- a/lib/tevent/tevent_poll.c +++ b/lib/tevent/tevent_poll.c @@ -58,9 +58,6 @@ struct poll_event_context { * Signal fd to wake the poll() thread */ int signal_fd; - - /* information for exiting from the event loop */ - int exit_code; }; static int poll_event_context_destructor(struct poll_event_context *poll_ev) -- 1.9.1 From c8ae741ac82734d125b2306511cab46a1fce26ac Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 22 Jul 2014 14:54:11 +0200 Subject: [PATCH 35/55] tevent: remove unused exit_code in tevent_select.c Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit a65df7e8c0ce687625a18de5769bf38f92118eca) --- lib/tevent/tevent_select.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/tevent/tevent_select.c b/lib/tevent/tevent_select.c index 73f27b7..40a4dc0 100644 --- a/lib/tevent/tevent_select.c +++ b/lib/tevent/tevent_select.c @@ -35,9 +35,6 @@ struct select_event_context { /* the maximum file descriptor number in fd_events */ int maxfd; - - /* information for exiting from the event loop */ - int exit_code; }; /* @@ -198,7 +195,7 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru fatal error. */ tevent_debug(select_ev->ev, TEVENT_DEBUG_FATAL, "ERROR: EBADF on select_event_loop_once\n"); - select_ev->exit_code = EBADF; + errno = select_errno; return -1; } -- 1.9.1 From 71314b59a7c15e585e791c03b809162897765dbe Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 30 Sep 2014 14:44:30 +0200 Subject: [PATCH 36/55] tevent: version 0.9.22 * pkgconfig fixes * Bug #10640 - smbd is not responding - tevent_common_signal_handler() increments non-atomic variables. https://bugzilla.samba.org/show_bug.cgi?id=10640 * Minor compile fixes Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 1dbd0bec040060193f1d2f1b5a97db1bd340c1ca) --- lib/tevent/ABI/tevent-0.9.22.sigs | 88 +++++++++++++++++++++++++++++++++++++++ lib/tevent/wscript | 2 +- 2 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 lib/tevent/ABI/tevent-0.9.22.sigs 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/wscript b/lib/tevent/wscript index 8d29e04..a991fed 100755 --- a/lib/tevent/wscript +++ b/lib/tevent/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'tevent' -VERSION = '0.9.21' +VERSION = '0.9.22' blddir = 'bin' -- 1.9.1 From 653f00bced0c729558e9539ca93176afd64b9c98 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Fri, 23 Jan 2015 21:56:19 -0800 Subject: [PATCH 37/55] Update the tevent_data.dox tutrial stuff to fix some errors, including white space problems. Signed-off-by: Richard Sharpe Reviewed-by: Ralph Boehme Autobuild-User(master): Richard Sharpe Autobuild-Date(master): Sat Jan 24 09:33:03 CET 2015 on sn-devel-104 (cherry picked from commit 6a56bdf9869162e57c816c067598552bd33c2910) (cherry picked from commit 2f50cd2554ac400ea1fc2e6aa5c7127d8b5f876f) --- lib/tevent/doc/tevent_data.dox | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/lib/tevent/doc/tevent_data.dox b/lib/tevent/doc/tevent_data.dox index 4ee4ac2..dbe7a04 100644 --- a/lib/tevent/doc/tevent_data.dox +++ b/lib/tevent/doc/tevent_data.dox @@ -46,18 +46,19 @@ struct testA { static void foo_done(struct tevent_req *req) { -// a->x contains 9 -struct foo_state *a = tevent_req_data(req, struct foo_state); + // a->x contains 10 since it came from foo_send + struct foo_state *a = tevent_req_data(req, struct foo_state); -// b->y contains 10 -struct testA *b = tevent_req_callback_data(req, struct testA); + // b->y contains 9 since it came from run + struct testA *b = tevent_req_callback_data(req, struct testA); -// c->y contains 10 -struct testA *c = (struct testA *)tevent_req_callback_data_void(req); + // 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); + printf("a->x: %d\n", a->x); + printf("b->y: %d\n", b->y); + printf("c->y: %d\n", c->y); } @@ -77,6 +78,9 @@ 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); @@ -101,7 +105,7 @@ int main (int argc, char **argv) { return EXIT_FAILURE; data = talloc(mem_ctx, struct testA); - data->y = 10; + data->y = 11; time_event = tevent_add_timer(event_ctx, mem_ctx, @@ -125,9 +129,9 @@ int main (int argc, char **argv) { Output of this example is: @code -a->x: 9 -b->y: 10 -c->y: 10 +a->x: 10 +b->y: 9 +c->y: 9 @endcode */ -- 1.9.1 From ebdc50018b6613eb58a8fd6e35f23b70596e5947 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 22 Jul 2013 14:23:33 -0700 Subject: [PATCH 38/55] Add Solaris ports as a tevent backend. Signed-off-by: Jeremy Allison Reviewed-by: David Disseldorp Autobuild-User(master): David Disseldorp Autobuild-Date(master): Sun Feb 15 23:25:07 CET 2015 on sn-devel-104 (cherry picked from commit 88c1eb4ae10a9f69d2e828b4e5543915c1d990c6) (cherry picked from commit bc8585b0120eb5956a0b9397fe07902c76fea072) --- lib/replace/system/select.h | 4 + lib/replace/wscript | 5 + lib/tevent/tevent.c | 5 +- lib/tevent/tevent_internal.h | 3 + lib/tevent/tevent_port.c | 779 +++++++++++++++++++++++++++++++++++++++++++ lib/tevent/wscript | 3 + 6 files changed, 798 insertions(+), 1 deletion(-) create mode 100644 lib/tevent/tevent_port.c diff --git a/lib/replace/system/select.h b/lib/replace/system/select.h index 11c5390..9e945c3 100644 --- a/lib/replace/system/select.h +++ b/lib/replace/system/select.h @@ -34,6 +34,10 @@ #include #endif +#ifdef HAVE_SOLARIS_PORTS +#include +#endif + #ifndef SELECT_CAST #define SELECT_CAST #endif diff --git a/lib/replace/wscript b/lib/replace/wscript index f0040b1..e64d849 100644 --- a/lib/replace/wscript +++ b/lib/replace/wscript @@ -76,6 +76,7 @@ struct foo bar = { .y = 'X', .x = 1 }; conf.CHECK_HEADERS('libaio.h locale.h ndir.h pwd.h') conf.CHECK_HEADERS('shadow.h sys/acl.h') conf.CHECK_HEADERS('sys/attributes.h attr/attributes.h sys/capability.h sys/dir.h sys/epoll.h') + conf.CHECK_HEADERS('port.h') conf.CHECK_HEADERS('sys/fcntl.h sys/filio.h sys/filsys.h sys/fs/s5param.h sys/fs/vx/quota.h') conf.CHECK_HEADERS('sys/id.h sys/ioctl.h sys/ipc.h sys/mman.h sys/mode.h sys/ndir.h sys/priv.h') conf.CHECK_HEADERS('sys/resource.h sys/security.h sys/shm.h sys/statfs.h sys/statvfs.h sys/termio.h') @@ -317,6 +318,7 @@ struct foo bar = { .y = 'X', .x = 1 }; conf.CHECK_FUNCS('timegm getifaddrs freeifaddrs mmap setgroups syscall setsid') conf.CHECK_FUNCS('getgrent_r getgrgid_r getgrnam_r getgrouplist getpagesize') conf.CHECK_FUNCS('getpwent_r getpwnam_r getpwuid_r epoll_create') + conf.CHECK_FUNCS('port_create') conf.SET_TARGET_TYPE('attr', 'EMPTY') @@ -457,6 +459,9 @@ removeea setea if conf.CONFIG_SET('HAVE_EPOLL_CREATE') and conf.CONFIG_SET('HAVE_SYS_EPOLL_H'): conf.DEFINE('HAVE_EPOLL', 1) + if conf.CONFIG_SET('HAVE_PORT_CREATE') and conf.CONFIG_SET('HAVE_PORT_H'): + conf.DEFINE('HAVE_SOLARIS_PORTS', 1) + conf.CHECK_HEADERS('poll.h') conf.CHECK_FUNCS('poll') diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c index be0afd4..843cf05 100644 --- a/lib/tevent/tevent.c +++ b/lib/tevent/tevent.c @@ -123,9 +123,12 @@ static void tevent_backend_init(void) tevent_select_init(); tevent_poll_init(); tevent_poll_mt_init(); -#ifdef HAVE_EPOLL +#if defined(HAVE_EPOLL) tevent_epoll_init(); +#elif defined(HAVE_SOLARIS_PORTS) + tevent_port_init(); #endif + tevent_standard_init(); } diff --git a/lib/tevent/tevent_internal.h b/lib/tevent/tevent_internal.h index d25dc05..10cc4a4 100644 --- a/lib/tevent/tevent_internal.h +++ b/lib/tevent/tevent_internal.h @@ -351,6 +351,9 @@ 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, diff --git a/lib/tevent/tevent_port.c b/lib/tevent/tevent_port.c new file mode 100644 index 0000000..93e94b2 --- /dev/null +++ b/lib/tevent/tevent_port.c @@ -0,0 +1,779 @@ +/* + 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 . +*/ + +#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 = 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) { + if (val->associated_event) { + continue; + } + int 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; + + if (port_ev->pid == getpid()) { + 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 = getpid(); + 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 && ev->signal_events) { + if (tevent_common_check_signal(ev)) { + return 0; + } + } + + if (ret == -1 && port_errno == ETIME && tvalp) { + /* we don't care about a possible delay here */ + tevent_common_loop_timer_delay(ev); + return 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) { + fde->handler(ev, fde, flags, fde->private_data); + break; + } + } + + 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->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/wscript b/lib/tevent/wscript index a991fed..45f602c 100755 --- a/lib/tevent/wscript +++ b/lib/tevent/wscript @@ -89,6 +89,9 @@ def build(bld): 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 -- 1.9.1 From 418d93b2f7699d675b525ea15e84e65a77c6e61a Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 27 Feb 2015 00:27:29 +0100 Subject: [PATCH 39/55] tevent: version 0.9.23 * Add Solaris ports as tevent backend. * Improvements to the tevent_data tutorial. * Remove use of the 'staticforward' macro. Signed-off-by: Michael Adam Reviewed-by: Stefan Metzmacher Autobuild-User(master): Michael Adam Autobuild-Date(master): Fri Feb 27 03:48:57 CET 2015 on sn-devel-104 (cherry picked from commit 04b8e19e1708c5670d180f5cd86d8ed139e9e5a4) The last 3 patches address BUG: https://bugzilla.samba.org/show_bug.cgi?id=11118 Add Solaris Ports as a tevent backend (cherry picked from commit d0a5a6f4797efb167086d54b47c61c0e89634f15) --- lib/tevent/ABI/tevent-0.9.23.sigs | 88 +++++++++++++++++++++++++++++++++++++++ lib/tevent/wscript | 2 +- 2 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 lib/tevent/ABI/tevent-0.9.23.sigs 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/wscript b/lib/tevent/wscript index 45f602c..489ce31 100755 --- a/lib/tevent/wscript +++ b/lib/tevent/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'tevent' -VERSION = '0.9.22' +VERSION = '0.9.23' blddir = 'bin' -- 1.9.1 From 66f4839d57b79865dd46deb2164ce639b08ec4e4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 2 Mar 2015 16:17:54 -0800 Subject: [PATCH 40/55] tevent: Ignore unexpected signal events in the same way the epoll backend does. Bug: https://bugzilla.samba.org/show_bug.cgi?id=11118 Signed-off-by: Jeremy Allison Reviewed-by: David Disseldorp Autobuild-User(master): David Disseldorp Autobuild-Date(master): Tue Mar 3 17:33:06 CET 2015 on sn-devel-104 (cherry picked from commit 7be3a5f92ddbb378a3c80e455cb7403f7861efa1) (cherry picked from commit 5db8d198ad7045d6bcb8e41701d045e92405c108) --- lib/tevent/tevent_port.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/tevent/tevent_port.c b/lib/tevent/tevent_port.c index 93e94b2..dd4958e 100644 --- a/lib/tevent/tevent_port.c +++ b/lib/tevent/tevent_port.c @@ -483,10 +483,16 @@ static int port_event_loop(struct port_event_context *port_ev, struct timeval *t port_errno = errno; tevent_trace_point_callback(ev, TEVENT_TRACE_AFTER_WAIT); - if (ret == -1 && port_errno == EINTR && ev->signal_events) { - if (tevent_common_check_signal(ev)) { - return 0; + 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 && tvalp) { -- 1.9.1 From f60675018b886529192754a3731217c8fb9b4077 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Tue, 3 Mar 2015 23:58:09 +0100 Subject: [PATCH 41/55] tevent: version 0.9.24 * Ignore unsolicited signal wakeup in tevent_port event loop. Signed-off-by: David Disseldorp Reviewed-by: Stefan Metzmacher Autobuild-User(master): Stefan Metzmacher Autobuild-Date(master): Wed Mar 4 08:33:06 CET 2015 on sn-devel-104 (cherry picked from commit 89788dd3193633f5e88ff194219ad838dcdfab96) Autobuild-User(v4-2-test): Stefan Metzmacher Autobuild-Date(v4-2-test): Wed Mar 4 15:07:48 CET 2015 on sn-devel-104 (cherry picked from commit 1309af4880eb00cf127aa3c1fc7b590c7000a4ec) --- lib/tevent/ABI/tevent-0.9.24.sigs | 88 +++++++++++++++++++++++++++++++++++++++ lib/tevent/wscript | 2 +- 2 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 lib/tevent/ABI/tevent-0.9.24.sigs 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/wscript b/lib/tevent/wscript index 489ce31..0da8232 100755 --- a/lib/tevent/wscript +++ b/lib/tevent/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'tevent' -VERSION = '0.9.23' +VERSION = '0.9.24' blddir = 'bin' -- 1.9.1 From a7eaa1bb3214313c3d9b5611ef80fd9ef4852baf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 31 Mar 2015 21:15:53 +0200 Subject: [PATCH 42/55] tevent: Fix CID 1035381 Unchecked return value Signed-off-by: Volker Lendecke Reviewed-by: Michael Adam (cherry picked from commit 6bcc037b5b636e88a914f1d39a95eb6eb72937e0) --- lib/tevent/testsuite.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/tevent/testsuite.c b/lib/tevent/testsuite.c index 34d13bb..e9d1ef4 100644 --- a/lib/tevent/testsuite.c +++ b/lib/tevent/testsuite.c @@ -121,6 +121,7 @@ static bool test_event_context(struct torture_context *test, #endif int finished=0; struct timeval t; + int ret; ev_ctx = tevent_context_init_byname(test, backend); if (ev_ctx == NULL) { @@ -135,7 +136,8 @@ static bool test_event_context(struct torture_context *test, fde_count = 0; /* create a pipe */ - pipe(fd); + 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); -- 1.9.1 From b5b8486189556294a0f48c727244fe087734902d Mon Sep 17 00:00:00 2001 From: Gordon Ross Date: Wed, 29 Apr 2015 11:34:10 -0700 Subject: [PATCH 43/55] lib: tevent: Fix compile error in Solaris ports backend. Signed-off-by: Gordon Ross Reviewed-by: Jeremy Allison Reviewed-by: Michael Adam (cherry picked from commit a7d41e94603d789bb461b84380a8fba3f837bc4f) --- lib/tevent/tevent_port.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/tevent/tevent_port.c b/lib/tevent/tevent_port.c index dd4958e..5b487d7 100644 --- a/lib/tevent/tevent_port.c +++ b/lib/tevent/tevent_port.c @@ -174,10 +174,11 @@ 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; } - int ret = port_associate(port_ev->port_fd, + ret = port_associate(port_ev->port_fd, PORT_SOURCE_FD, (uintptr_t)val->fde->fd, val->events, -- 1.9.1 From 179a297fce0369ca62884d5ce77b7a6badcfcc82 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 18 May 2015 13:25:33 +0200 Subject: [PATCH 44/55] tevent: add a note to tevent_add_fd() BUG: https://bugzilla.samba.org/show_bug.cgi?id=11141 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison (cherry picked from commit 33ca0179ac091c8bb1c2b3fa7999cc5047d09a80) --- lib/tevent/tevent.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index c54cbe2..6861ffb 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -176,6 +176,11 @@ void tevent_set_default_backend(const char *backend); * * @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, -- 1.9.1 From 4966dce08e9bee91000c046197d55a96f038c3e0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 2 Jun 2015 12:18:22 +0200 Subject: [PATCH 45/55] tevent: fix access after free in tevent_common_check_signal() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was reported by Pavel Březina : We found a crash in SSSD when a tevent signal is freed in its handler, tevent than crashes when it access siginfo. sig_info is freed in signal destructor: > #ifdef SA_SIGINFO > if (se->sa_flags & SA_SIGINFO) { > if (sig_state->sig_info[se->signum]) { > talloc_free(sig_state->sig_info[se->signum]); > sig_state->sig_info[se->signum] = NULL; > } > } > #endif (gdb) bt #0 0x00007f5d4d86cc74 in tevent_signal_destructor (se=0x7f5d5370f920) at ../tevent_signal.c:213 #1 0x00007f5d4d65f233 in _talloc_free_internal () from /lib64/libtalloc.so.2 #2 0x00007f5d4d6593a3 in _talloc_free () from /lib64/libtalloc.so.2 #3 0x00007f5d4342f3d4 in proxy_child_init_done (subreq=0x7f5d5370f600) at src/providers/proxy/proxy_auth.c:436 #4 0x00007f5d4d86b0c2 in _tevent_req_error (req=req@entry=0x7f5d5370f600, error=error@entry=5, location=location@entry=0x7f5d43433010 "src/providers/proxy/proxy_auth.c:356") at ../tevent_req.c:167 #5 0x00007f5d4342ef5e in pc_init_sig_handler (ev=, sige=, signum=, count=, __siginfo=, pvt=) at src/providers/proxy/proxy_auth.c:356 #6 0x00007f5d4d86d48c in tevent_common_check_signal (ev=0x7f5d536de670) at ../tevent_signal.c:428 #7 0x00007f5d4d86f28c in epoll_event_loop (tvalp=0x7fff7b568490, epoll_ev=0x7f5d536de8b0) at ../tevent_epoll.c:647 #8 epoll_event_loop_once (ev=, location=) at ../tevent_epoll.c:926 #9 0x00007f5d4d86d7d7 in std_event_loop_once (ev=0x7f5d536de670, location=0x7f5d50faedc3 "src/util/server.c:668") at ../tevent_standard.c:114 #10 0x00007f5d4d869fbd in _tevent_loop_once (ev=ev@entry=0x7f5d536de670, location=location@entry=0x7f5d50faedc3 "src/util/server.c:668") at ../tevent.c:530 #11 0x00007f5d4d86a15b in tevent_common_loop_wait (ev=0x7f5d536de670, location=0x7f5d50faedc3 "src/util/server.c:668") at ../tevent.c:634 #12 0x00007f5d4d86d777 in std_event_loop_wait (ev=0x7f5d536de670, location=0x7f5d50faedc3 "src/util/server.c:668") at ../tevent_standard.c:140 #13 0x00007f5d50f96863 in server_loop (main_ctx=0x7f5d536dfac0) at src/util/server.c:668 #14 0x00007f5d5180aa42 in main (argc=8, argv=) at src/providers/data_provider_be.c:2909 But then it is accessed again in tevent_common_check_signal: > #ifdef SA_SIGINFO > if (clear_processed_siginfo) { > uint32_t j; > for (j=0;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 (gdb) bt #0 0x00007fd7ba400505 in memset (__len=, __ch=, __dest=) at /usr/include/bits/string3.h:84 #1 tevent_common_check_signal (ev=0x7fd7bfddf670) at ../tevent_signal.c:459 #2 0x00007fd7ba40228c in epoll_event_loop (tvalp=0x7fff85536430, epoll_ev=0x7fd7bfddf8b0) at ../tevent_epoll.c:647 #3 epoll_event_loop_once (ev=, location=) at ../tevent_epoll.c:926 #4 0x00007fd7ba4007d7 in std_event_loop_once (ev=0x7fd7bfddf670, location=0x7fd7bdb417c3 "src/util/server.c:668") at ../tevent_standard.c:114 #5 0x00007fd7ba3fcfbd in _tevent_loop_once (ev=ev@entry=0x7fd7bfddf670, location=location@entry=0x7fd7bdb417c3 "src/util/server.c:668") at ../tevent.c:530 #6 0x00007fd7ba3fd15b in tevent_common_loop_wait (ev=0x7fd7bfddf670, location=0x7fd7bdb417c3 "src/util/server.c:668") at ../tevent.c:634 #7 0x00007fd7ba400777 in std_event_loop_wait (ev=0x7fd7bfddf670, location=0x7fd7bdb417c3 "src/util/server.c:668") at ../tevent_standard.c:140 #8 0x00007fd7bdb29343 in server_loop (main_ctx=0x7fd7bfde0ac0) at src/util/server.c:668 #9 0x00007fd7be39ca42 in main (argc=8, argv=) at src/providers/data_provider_be.c:2909 BUG: https://bugzilla.samba.org/show_bug.cgi?id=11308 Signed-off-by: Stefan Metzmacher Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Tue Jun 2 21:02:11 CEST 2015 on sn-devel-104 (cherry picked from commit 9d797ffb27bf4be100c900b0373f62b029679de3) --- lib/tevent/tevent_signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tevent/tevent_signal.c b/lib/tevent/tevent_signal.c index b54da2e..924dc05 100644 --- a/lib/tevent/tevent_signal.c +++ b/lib/tevent/tevent_signal.c @@ -457,7 +457,7 @@ int tevent_common_check_signal(struct tevent_context *ev) } #ifdef SA_SIGINFO - if (clear_processed_siginfo) { + if (clear_processed_siginfo && sig_state->sig_info[i] != NULL) { uint32_t j; for (j=0;j Date: Thu, 4 Dec 2014 12:44:56 +0100 Subject: [PATCH 46/55] pytevent: Better error and reference handling py_backend_list: - Handle cases of PyString_FromString or PyList_Append failing. - Properly decrease the reference count of the returned strings. py_register_backend: - Decref "name" after use Signed-off-by: Petr Viktorin Reviewed-by: Andrew Bartlett Reviewed-by: Jelmer Vernooij (cherry picked from commit f5838df58ea36e64cd0295b595df9cbd10d8c757) --- lib/tevent/pytevent.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index 870f5aa..5b8c535 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -177,14 +177,18 @@ static PyObject *py_register_backend(PyObject *self, PyObject *args) if (!PyString_Check(name)) { PyErr_SetNone(PyExc_TypeError); + Py_DECREF(name); return NULL; } if (!tevent_register_backend(PyString_AsString(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; } @@ -684,9 +688,10 @@ static PyObject *py_set_default_backend(PyObject *self, PyObject *args) static PyObject *py_backend_list(PyObject *self) { - PyObject *ret; - int i; - const char **backends; + PyObject *ret = NULL; + PyObject *string = NULL; + int i, result; + const char **backends = NULL; ret = PyList_New(0); if (ret == NULL) { @@ -696,16 +701,30 @@ static PyObject *py_backend_list(PyObject *self) backends = tevent_backend_list(NULL); if (backends == NULL) { PyErr_SetNone(PyExc_RuntimeError); - Py_DECREF(ret); - return NULL; + goto err; } for (i = 0; backends[i]; i++) { - PyList_Append(ret, PyString_FromString(backends[i])); + string = PyString_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[] = { -- 1.9.1 From 189aef83bb15047bf8cd7760edaae53e0cf62299 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 22 May 2015 13:29:11 +0200 Subject: [PATCH 47/55] pytevent: Define missing TeventFd_Type object The type objects for Fd was declared but never defined, resulting in segfaults when it was used. Define it. Signed-off-by: Petr Viktorin Reviewed-by: Andrew Bartlett Reviewed-by: Jelmer Vernooij (cherry picked from commit 4399dc582fa06b04e1cec1d3aa59cd332e4b5ba2) --- lib/tevent/pytevent.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index 5b8c535..ef891d4 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -415,6 +415,19 @@ static void py_fd_handler(struct tevent_context *ev, 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; -- 1.9.1 From e2af9e15dfa9af63b066e0acac40ea528e6d0ed4 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 26 May 2015 13:25:12 +0200 Subject: [PATCH 48/55] pytalloc: Improve timer wrapper, and test it Using Context.add_timer resulted in crashes due to missing type object and bad reference handling. Add a TeventTimer_Type struct, and introduce a clear ownership/lifetime model. Add a "add_timer_offset" to allow adding timers from Python. (add_timer requires passing struct timeval as a Python integer, which can't really be done portably). Add tests. Signed-off-by: Petr Viktorin Reviewed-by: Andrew Bartlett Reviewed-by: Jelmer Vernooij (similar to commit 560576217f11b132f9c32de6e41c623dbc152137) (We don't run the tests in the backport) --- lib/tevent/bindings.py | 52 ++++++++++++++++- lib/tevent/pytevent.c | 147 +++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 181 insertions(+), 18 deletions(-) diff --git a/lib/tevent/bindings.py b/lib/tevent/bindings.py index 1060caf..55aafbb 100644 --- a/lib/tevent/bindings.py +++ b/lib/tevent/bindings.py @@ -22,8 +22,10 @@ # License along with this library; if not, see . import signal +from unittest import TestCase, TestProgram +import gc + import _tevent -from unittest import TestCase class BackendListTests(TestCase): @@ -60,3 +62,51 @@ class ContextTests(TestCase): 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/pytevent.c b/lib/tevent/pytevent.c index ef891d4..a25dc93 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -50,6 +50,7 @@ typedef struct { typedef struct { PyObject_HEAD struct tevent_timer *timer; + PyObject *callback; } TeventTimer_Object; typedef struct { @@ -372,38 +373,148 @@ static void py_timer_handler(struct tevent_context *ev, struct timeval current_time, void *private_data) { - PyObject *callback = private_data, *ret; - ret = PyObject_CallFunction(callback, "l", te); + TeventTimer_Object *self = private_data; + PyObject *ret; + + ret = PyObject_CallFunction(self->callback, "l", te); + if (ret == NULL) { + /* No Python stack to propagate exception to; just print traceback */ + PyErr_PrintEx(0); + } Py_XDECREF(ret); } -static PyObject *py_tevent_context_add_timer(TeventContext_Object *self, PyObject *args) +static void py_tevent_timer_dealloc(TeventTimer_Object *self) { - TeventTimer_Object *ret; - struct timeval next_event; - struct tevent_timer *timer; - PyObject *handler; - if (!PyArg_ParseTuple(args, "lO", &next_event, &handler)) - return NULL; - - timer = tevent_add_timer(self->ev, NULL, next_event, py_timer_handler, - handler); - if (timer == NULL) { - PyErr_SetNone(PyExc_RuntimeError); - return NULL; + 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) { + return PyBool_FromLong(self->timer != NULL); +} + +struct PyGetSetDef py_tevent_timer_getset[] = { + { + .name = "active", + .get = (getter)py_tevent_timer_get_active, + .doc = "true if the timer is scheduled to run", + }, + {NULL}, +}; + +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, +}; + +static int timer_destructor(void* ptr) +{ + TeventTimer_Object *obj = *(TeventTimer_Object **)ptr; + obj->timer = NULL; + Py_DECREF(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; + TeventTimer_Object **tmp_context; ret = PyObject_New(TeventTimer_Object, &TeventTimer_Type); if (ret == NULL) { PyErr_NoMemory(); - talloc_free(timer); return NULL; } - ret->timer = timer; + 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; + } + tmp_context = talloc(ret->timer, TeventTimer_Object*); + if (tmp_context == NULL) { + talloc_free(ret->timer); + Py_DECREF(ret); + PyErr_SetString(PyExc_RuntimeError, "Could not initialize timer"); + return NULL; + } + Py_INCREF(ret); + *tmp_context = ret; + talloc_set_destructor(tmp_context, timer_destructor); return (PyObject *)ret; } +static PyObject *py_tevent_context_add_timer(TeventContext_Object *self, PyObject *args) +{ + struct timeval next_event; + PyObject *callback; + if (!PyArg_ParseTuple(args, "lO", &next_event, &callback)) + return NULL; + + 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, @@ -479,6 +590,8 @@ static PyMethodDef py_tevent_context_methods[] = { 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_seconds, handler) -> timer" }, { "add_fd", (PyCFunction)py_tevent_context_add_fd, METH_VARARGS, "S.add_fd(fd, flags, handler) -> fd" }, #ifdef TEVENT_DEPRECATED -- 1.9.1 From e483e7a6e874727e1595c9d2b949a7efb8e6ab0b Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Fri, 22 May 2015 11:47:56 +0200 Subject: [PATCH 49/55] pytevent: Port to Python 3 - Use PyStr (String on py2, Unicode on py3) for text strings - Use PyLong instead of PyInt on Python 3 - Use new module initialization Signed-off-by: Petr Viktorin Reviewed-by: Andrew Bartlett Reviewed-by: Jelmer Vernooij (cherry picked from commit 8dbdd27526c4d5358bc2614e90f9aca36f41ed1a) --- lib/tevent/pytevent.c | 70 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 13 deletions(-) diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index a25dc93..160ea1a 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -25,6 +25,17 @@ #include #include +#if PY_MAJOR_VERSION >= 3 +#define PyStr_Check PyUnicode_Check +#define PyStr_FromString PyUnicode_FromString +#define PyStr_AsUTF8 PyUnicode_AsUTF8 +#define PyInt_FromLong PyLong_FromLong +#else +#define PyStr_Check PyString_Check +#define PyStr_FromString PyString_FromString +#define PyStr_AsUTF8 PyString_AsString +#endif + void init_tevent(void); typedef struct { @@ -176,13 +187,13 @@ static PyObject *py_register_backend(PyObject *self, PyObject *args) return NULL; } - if (!PyString_Check(name)) { + if (!PyStr_Check(name)) { PyErr_SetNone(PyExc_TypeError); Py_DECREF(name); return NULL; } - if (!tevent_register_backend(PyString_AsString(name), &py_tevent_ops)) { /* FIXME: What to do with backend */ + if (!tevent_register_backend(PyStr_AsUTF8(name), &py_tevent_ops)) { /* FIXME: What to do with backend */ PyErr_SetNone(PyExc_RuntimeError); Py_DECREF(name); return NULL; @@ -830,7 +841,7 @@ static PyObject *py_backend_list(PyObject *self) goto err; } for (i = 0; backends[i]; i++) { - string = PyString_FromString(backends[i]); + string = PyStr_FromString(backends[i]); if (!string) { goto err; } @@ -863,31 +874,48 @@ static PyMethodDef tevent_methods[] = { { NULL }, }; -void init_tevent(void) +#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; + return NULL; if (PyType_Ready(&TeventQueue_Type) < 0) - return; + return NULL; if (PyType_Ready(&TeventReq_Type) < 0) - return; + return NULL; if (PyType_Ready(&TeventSignal_Type) < 0) - return; + return NULL; if (PyType_Ready(&TeventTimer_Type) < 0) - return; + return NULL; if (PyType_Ready(&TeventFd_Type) < 0) - return; + return NULL; - m = Py_InitModule3("_tevent", tevent_methods, "Tevent integration for twisted."); +#if PY_MAJOR_VERSION >= 3 + m = PyModule_Create(&moduledef); +#else + m = Py_InitModule3("_tevent", tevent_methods, MODULE_DOC); +#endif if (m == NULL) - return; + return NULL; Py_INCREF(&TeventContext_Type); PyModule_AddObject(m, "Context", (PyObject *)&TeventContext_Type); @@ -907,5 +935,21 @@ void init_tevent(void) Py_INCREF(&TeventFd_Type); PyModule_AddObject(m, "Fd", (PyObject *)&TeventFd_Type); - PyModule_AddObject(m, "__version__", PyString_FromString(PACKAGE_VERSION)); + 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 -- 1.9.1 From b850c4ea135217700646eb5ad0583b90b62c607f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 30 May 2015 01:42:08 +0200 Subject: [PATCH 50/55] tevent/testsuite: make sure we cleanup tevent_fd structures in the correct order First we need to remove the tevent_fd structures without tevent_fd_set_auto_close(). Closing the fd needs to be the last thing... BUG: https://bugzilla.samba.org/show_bug.cgi?id=11316 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit 88971d4870a197f656ef912911ca1e4ff5b56749) --- lib/tevent/testsuite.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tevent/testsuite.c b/lib/tevent/testsuite.c index e9d1ef4..c63c878 100644 --- a/lib/tevent/testsuite.c +++ b/lib/tevent/testsuite.c @@ -177,10 +177,10 @@ static bool test_event_context(struct torture_context *test, } } - talloc_free(fde_read); - talloc_free(fde_write); 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) { -- 1.9.1 From 421896dbb7c063edbbcfa2d16af0b9f65e919321 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 28 May 2015 09:32:26 +0200 Subject: [PATCH 51/55] tevent.h: propose tstream_ versions of read_packet_send/recv and writev_send/recv The functions operating on the raw file descriptor are for advanced callers, which take extra care and avoid the problems of https://bugzilla.samba.org/show_bug.cgi?id=11141. BUG: https://bugzilla.samba.org/show_bug.cgi?id=11316 Signed-off-by: Stefan Metzmacher Reviewed-by: Volker Lendecke Reviewed-by: Jeremy Allison (cherry picked from commit 44584f810720602201a9afaaa087eeb83579eff5) --- lib/tevent/tevent.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h index 6861ffb..b6c39d1 100644 --- a/lib/tevent/tevent.h +++ b/lib/tevent/tevent.h @@ -616,8 +616,8 @@ void tevent_get_trace_callback(struct tevent_context *ev, * 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: read_packet_send/recv and writev_send/recv. These - * requests are much easier to compose than the low-level event + * 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 -- 1.9.1 From 465849f686af91171dd4f7c1eee664bc5c791538 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 11 Jun 2015 09:49:18 +0200 Subject: [PATCH 52/55] pytevent: remove dead code TEVENT_DEPRECATED is never defined Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 1a8a5ba0d51f9c2c9e84a3400e05327e7059156b) --- lib/tevent/pytevent.c | 48 ------------------------------------------------ 1 file changed, 48 deletions(-) diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index 160ea1a..02211ed 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -295,38 +295,6 @@ static PyObject *py_tevent_context_loop_once(TeventContext_Object *self) Py_RETURN_NONE; } -#ifdef TEVENT_DEPRECATED -static bool py_tevent_finished(PyObject *callback) -{ - PyObject *py_ret; - bool ret; - - py_ret = PyObject_CallFunction(callback, ""); - if (py_ret == NULL) - return true; - ret = PyObject_IsTrue(py_ret); - Py_DECREF(py_ret); - return ret; -} - -static PyObject *py_tevent_context_loop_until(TeventContext_Object *self, PyObject *args) -{ - PyObject *callback; - if (!PyArg_ParseTuple(args, "O", &callback)) - return NULL; - - if (tevent_loop_until(self->ev, py_tevent_finished, callback) != 0) { - PyErr_SetNone(PyExc_RuntimeError); - return NULL; - } - - if (PyErr_Occurred()) - return NULL; - - Py_RETURN_NONE; -} -#endif - static void py_tevent_signal_handler(struct tevent_context *ev, struct tevent_signal *se, int signum, @@ -576,14 +544,6 @@ static PyObject *py_tevent_context_add_fd(TeventContext_Object *self, PyObject * return (PyObject *)ret; } -#ifdef TEVENT_DEPRECATED -static PyObject *py_tevent_context_set_allow_nesting(TeventContext_Object *self) -{ - tevent_loop_allow_nesting(self->ev); - Py_RETURN_NONE; -} -#endif - static PyMethodDef py_tevent_context_methods[] = { { "reinitialise", (PyCFunction)py_tevent_context_reinitialise, METH_NOARGS, "S.reinitialise()" }, @@ -593,10 +553,6 @@ static PyMethodDef py_tevent_context_methods[] = { METH_NOARGS, "S.loop_wait()" }, { "loop_once", (PyCFunction)py_tevent_context_loop_once, METH_NOARGS, "S.loop_once()" }, -#ifdef TEVENT_DEPRECATED - { "loop_until", (PyCFunction)py_tevent_context_loop_until, - METH_VARARGS, "S.loop_until(callback)" }, -#endif { "add_signal", (PyCFunction)py_tevent_context_add_signal, METH_VARARGS, "S.add_signal(signum, sa_flags, handler) -> signal" }, { "add_timer", (PyCFunction)py_tevent_context_add_timer, @@ -605,10 +561,6 @@ static PyMethodDef py_tevent_context_methods[] = { METH_VARARGS, "S.add_timer(offset_seconds, handler) -> timer" }, { "add_fd", (PyCFunction)py_tevent_context_add_fd, METH_VARARGS, "S.add_fd(fd, flags, handler) -> fd" }, -#ifdef TEVENT_DEPRECATED - { "allow_nesting", (PyCFunction)py_tevent_context_set_allow_nesting, - METH_NOARGS, "Whether to allow nested tevent loops." }, -#endif { NULL }, }; -- 1.9.1 From 11a51a615ab783b3239076e104f21f267173fc87 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 11 Jun 2015 09:50:35 +0200 Subject: [PATCH 53/55] pytevent: remove const warnings using discard_const_p() Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit fb04f0f4190005ff21817b79d02897af23ddc7ee) --- lib/tevent/pytevent.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index 02211ed..a22bf26 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -23,6 +23,7 @@ */ #include +#include "replace.h" #include #if PY_MAJOR_VERSION >= 3 @@ -230,7 +231,7 @@ static void py_queue_trigger(struct tevent_req *req, void *private_data) { PyObject *callback = private_data, *ret; - ret = PyObject_CallFunction(callback, ""); + ret = PyObject_CallFunction(callback, discard_const_p(char, "")); Py_XDECREF(ret); } @@ -304,7 +305,7 @@ static void py_tevent_signal_handler(struct tevent_context *ev, { PyObject *callback = (PyObject *)private_data, *ret; - ret = PyObject_CallFunction(callback, "ii", signum, count); + ret = PyObject_CallFunction(callback, discard_const_p(char, "ii"), signum, count); Py_XDECREF(ret); } @@ -355,7 +356,7 @@ static void py_timer_handler(struct tevent_context *ev, TeventTimer_Object *self = private_data; PyObject *ret; - ret = PyObject_CallFunction(self->callback, "l", te); + 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); @@ -384,9 +385,9 @@ static PyObject* py_tevent_timer_get_active(TeventTimer_Object *self) { struct PyGetSetDef py_tevent_timer_getset[] = { { - .name = "active", + .name = discard_const_p(char, "active"), .get = (getter)py_tevent_timer_get_active, - .doc = "true if the timer is scheduled to run", + .doc = discard_const_p(char, "true if the timer is scheduled to run"), }, {NULL}, }; @@ -501,7 +502,7 @@ static void py_fd_handler(struct tevent_context *ev, { PyObject *callback = private_data, *ret; - ret = PyObject_CallFunction(callback, "i", flags); + ret = PyObject_CallFunction(callback, discard_const_p(char, "i"), flags); Py_XDECREF(ret); } @@ -595,8 +596,11 @@ static PyObject *py_tevent_req_is_in_progress(PyObject *self) } static PyGetSetDef py_tevent_req_getsetters[] = { - { "in_progress", (getter)py_tevent_req_is_in_progress, NULL, - "Whether the request is in progress" }, + { + .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"), + }, { NULL } }; @@ -684,8 +688,11 @@ static PyObject *py_tevent_queue_get_length(TeventQueue_Object *self) } static PyGetSetDef py_tevent_queue_getsetters[] = { - { "length", (getter)py_tevent_queue_get_length, - NULL, "The number of elements in the queue." }, + { + .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."), + }, { NULL }, }; @@ -711,8 +718,11 @@ static PyObject *py_tevent_context_signal_support(PyObject *_self) } static PyGetSetDef py_tevent_context_getsetters[] = { - { "signal_support", (getter)py_tevent_context_signal_support, - NULL, "if this platform and tevent context support signal handling" }, + { + .name = discard_const_p(char, "signal_support"), + .get = (getter)py_tevent_context_signal_support, + .doc = discard_const_p(char, "if this platform and tevent context support signal handling"), + }, { NULL } }; @@ -729,7 +739,7 @@ static PyObject *py_tevent_context_new(PyTypeObject *type, PyObject *args, PyObj struct tevent_context *ev; TeventContext_Object *ret; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwnames, &name)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", discard_const_p(char *, kwnames), &name)) return NULL; if (name == NULL) { -- 1.9.1 From 2ced4266b00d95db5f28803772977b30e6a542e9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 11 Jun 2015 09:51:19 +0200 Subject: [PATCH 54/55] pytevent: add a TeventTimer_Object_ref helper structure to make the code clearer This gives talloc_set_destructor to verify the type, which removes a compiler warning. Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit 93ee074f912da02d4c1f1584df9b107364b639be) --- lib/tevent/pytevent.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/tevent/pytevent.c b/lib/tevent/pytevent.c index a22bf26..752e251 100644 --- a/lib/tevent/pytevent.c +++ b/lib/tevent/pytevent.c @@ -401,11 +401,14 @@ static PyTypeObject TeventTimer_Type = { .tp_flags = Py_TPFLAGS_DEFAULT, }; -static int timer_destructor(void* ptr) +struct TeventTimer_Object_ref { + TeventTimer_Object *obj; +}; + +static int TeventTimer_Object_ref_destructor(struct TeventTimer_Object_ref *ref) { - TeventTimer_Object *obj = *(TeventTimer_Object **)ptr; - obj->timer = NULL; - Py_DECREF(obj); + ref->obj->timer = NULL; + Py_DECREF(ref->obj); return 0; } @@ -440,7 +443,7 @@ static PyObject *py_tevent_context_add_timer_internal(TeventContext_Object *self * The Python timer holds a reference to the callback. */ TeventTimer_Object *ret; - TeventTimer_Object **tmp_context; + struct TeventTimer_Object_ref *ref; ret = PyObject_New(TeventTimer_Object, &TeventTimer_Type); if (ret == NULL) { @@ -456,16 +459,17 @@ static PyObject *py_tevent_context_add_timer_internal(TeventContext_Object *self PyErr_SetString(PyExc_RuntimeError, "Could not initialize timer"); return NULL; } - tmp_context = talloc(ret->timer, TeventTimer_Object*); - if (tmp_context == 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); - *tmp_context = ret; - talloc_set_destructor(tmp_context, timer_destructor); + ref->obj = ret; + + talloc_set_destructor(ref, TeventTimer_Object_ref_destructor); return (PyObject *)ret; } -- 1.9.1 From 9e2e26aa1017e218d7e3c187841937e6dff6fe3f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 12 Jun 2015 08:58:26 +0200 Subject: [PATCH 55/55] tevent: version 0.9.25 * Fix compile error in Solaris ports backend. * Fix access after free in tevent_common_check_signal(). bug #11308 * Improve pytevent bindings. * Testsuite fixes. * Improve the documentation of the tevent_add_fd() assumtions. It must be talloc_free'ed before closing the fd! See bug #11141 and bug #11316. Signed-off-by: Stefan Metzmacher Reviewed-by: Michael Adam (cherry picked from commit d7bdb30cc1731dc84831e323332a85be2bccf6a7) --- lib/tevent/ABI/tevent-0.9.25.sigs | 88 +++++++++++++++++++++++++++++++++++++++ lib/tevent/wscript | 2 +- 2 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 lib/tevent/ABI/tevent-0.9.25.sigs 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/wscript b/lib/tevent/wscript index 0da8232..9abbd9b 100755 --- a/lib/tevent/wscript +++ b/lib/tevent/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'tevent' -VERSION = '0.9.24' +VERSION = '0.9.25' blddir = 'bin' -- 1.9.1