From 64e1d7b31b8e2482a5c8c3af49d4b580c4ae5538 Mon Sep 17 00:00:00 2001 From: "Galen.Liu" Date: Mon, 4 Feb 2013 07:43:01 +0100 Subject: [PATCH 01/34] tevent: fix --disable-python cause configure fails (bug #8718) When we disable python, it will cause build fail! so, the patch will fix it. Reviewed-by: Stefan Metzmacher --- lib/tevent/wscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tevent/wscript b/lib/tevent/wscript index 684286d..7b1d2af 100755 --- a/lib/tevent/wscript +++ b/lib/tevent/wscript @@ -92,7 +92,7 @@ def build(bld): pc_files='tevent.pc', private_library=private_library) - if not bld.CONFIG_SET('USING_SYSTEM_PYTEVENT'): + if not bld.CONFIG_SET('USING_SYSTEM_PYTEVENT') and not bld.env.disable_python: bld.SAMBA_PYTHON('pytevent', 'pytevent.c', deps='tevent', -- 1.7.9.5 From 646cb3ac5518a682df9b060e31a1869e2f42274d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 17 Feb 2013 16:36:25 +0100 Subject: [PATCH 02/34] tevent: fix compiler warning in tevent_context_init_byname() Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c index aa758de..3b273d6 100644 --- a/lib/tevent/tevent.c +++ b/lib/tevent/tevent.c @@ -273,7 +273,7 @@ struct tevent_context *tevent_context_init_ops(TALLOC_CTX *mem_ctx, struct tevent_context *tevent_context_init_byname(TALLOC_CTX *mem_ctx, const char *name) { - struct tevent_ops *ops; + const struct tevent_ops *ops; ops = tevent_find_ops_byname(name); if (ops == NULL) { -- 1.7.9.5 From 54cdb700488e301e3dd6df3f3e465b6a480a3af8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 15 Feb 2013 10:31:36 +0100 Subject: [PATCH 03/34] tevent: call epoll_panic() if EPOLL_CTL_DEL failed Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 8696215..fd0c6ff 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -240,9 +240,8 @@ static void epoll_del_event(struct epoll_event_context *epoll_ev, struct tevent_ event.events = epoll_map_flags(fde->flags); event.data.ptr = fde; if (epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event) != 0) { - tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL, - "epoll_del_event failed! probable early close bug (%s)\n", - strerror(errno)); + epoll_panic(epoll_ev, "EPOLL_CTL_DEL failed", false); + return; } fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; } -- 1.7.9.5 From 42d18cbe368b726b3309a64cec4b74cf08a608b0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 15 Feb 2013 11:24:59 +0100 Subject: [PATCH 04/34] tevent: remember the errno from select(), poll() and epoll_wait() Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 6 ++++-- lib/tevent/tevent_poll.c | 4 +++- lib/tevent/tevent_select.c | 6 ++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index fd0c6ff..c7e9894 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -312,6 +312,7 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval #define MAXEVENTS 1 struct epoll_event events[MAXEVENTS]; int timeout = -1; + int wait_errno; if (epoll_ev->epoll_fd == -1) return -1; @@ -327,15 +328,16 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval tevent_trace_point_callback(epoll_ev->ev, TEVENT_TRACE_BEFORE_WAIT); ret = epoll_wait(epoll_ev->epoll_fd, events, MAXEVENTS, timeout); + wait_errno = errno; tevent_trace_point_callback(epoll_ev->ev, TEVENT_TRACE_AFTER_WAIT); - if (ret == -1 && errno == EINTR && epoll_ev->ev->signal_events) { + if (ret == -1 && wait_errno == EINTR && epoll_ev->ev->signal_events) { if (tevent_common_check_signal(epoll_ev->ev)) { return 0; } } - if (ret == -1 && errno != EINTR) { + if (ret == -1 && wait_errno != EINTR) { epoll_panic(epoll_ev, "epoll_wait() failed", true); return -1; } diff --git a/lib/tevent/tevent_poll.c b/lib/tevent/tevent_poll.c index 89b3bbc..81a7176 100644 --- a/lib/tevent/tevent_poll.c +++ b/lib/tevent/tevent_poll.c @@ -444,6 +444,7 @@ static int poll_event_loop_poll(struct tevent_context *ev, int timeout = -1; unsigned first_fd; unsigned i; + int poll_errno; if (ev->signal_events && tevent_common_check_signal(ev)) { return 0; @@ -462,9 +463,10 @@ static int poll_event_loop_poll(struct tevent_context *ev, tevent_trace_point_callback(poll_ev->ev, TEVENT_TRACE_BEFORE_WAIT); pollrtn = poll(poll_ev->fds, poll_ev->num_fds, timeout); + poll_errno = errno; tevent_trace_point_callback(poll_ev->ev, TEVENT_TRACE_AFTER_WAIT); - if (pollrtn == -1 && errno == EINTR && ev->signal_events) { + if (pollrtn == -1 && poll_errno == EINTR && ev->signal_events) { tevent_common_check_signal(ev); return 0; } diff --git a/lib/tevent/tevent_select.c b/lib/tevent/tevent_select.c index 7e0c927..ffb0d18 100644 --- a/lib/tevent/tevent_select.c +++ b/lib/tevent/tevent_select.c @@ -144,6 +144,7 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru fd_set r_fds, w_fds; struct tevent_fd *fde; int selrtn; + int select_errno; /* we maybe need to recalculate the maxfd */ if (select_ev->maxfd == EVENT_INVALID_MAXFD) { @@ -175,15 +176,16 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru tevent_trace_point_callback(select_ev->ev, TEVENT_TRACE_BEFORE_WAIT); selrtn = select(select_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp); + select_errno = errno; tevent_trace_point_callback(select_ev->ev, TEVENT_TRACE_AFTER_WAIT); - if (selrtn == -1 && errno == EINTR && + if (selrtn == -1 && select_errno == EINTR && select_ev->ev->signal_events) { tevent_common_check_signal(select_ev->ev); return 0; } - if (selrtn == -1 && errno == EBADF) { + if (selrtn == -1 && select_errno == EBADF) { /* the socket is dead! this should never happen as the socket should have first been made readable and that should have removed -- 1.7.9.5 From 5f548eb3344b18da942713a6e4a8e4cf8a1e2d49 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 15 Feb 2013 12:10:26 +0100 Subject: [PATCH 05/34] tevent: add epoll_{create,ctl}_panic_fallback() for testing This makes sure we only do random panics if a fallback handler is registered. Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 54 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index c7e9894..3132367 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -44,11 +44,50 @@ struct epoll_event_context { }; #ifdef TEST_PANIC_FALLBACK -static int epoll_wait_panic_fallback(int epfd, - struct epoll_event *events, - int maxevents, - int timeout) + +static int epoll_create_panic_fallback(struct epoll_event_context *epoll_ev, + int size) +{ + if (epoll_ev->panic_fallback == NULL) { + return epoll_create(size); + } + + /* 50% of the time, fail... */ + if ((random() % 2) == 0) { + errno = EINVAL; + return -1; + } + + return epoll_create(size); +} + +static int epoll_ctl_panic_fallback(struct epoll_event_context *epoll_ev, + int epfd, int op, int fd, + struct epoll_event *event) +{ + if (epoll_ev->panic_fallback == NULL) { + return epoll_ctl(epfd, op, fd, event); + } + + /* 50% of the time, fail... */ + if ((random() % 2) == 0) { + errno = EINVAL; + return -1; + } + + return epoll_ctl(epfd, op, fd, event); +} + +static int epoll_wait_panic_fallback(struct epoll_event_context *epoll_ev, + int epfd, + struct epoll_event *events, + int maxevents, + int timeout) { + if (epoll_ev->panic_fallback == NULL) { + return epoll_wait(epfd, events, maxevents, timeout); + } + /* 50% of the time, fail... */ if ((random() % 2) == 0) { errno = EINVAL; @@ -58,7 +97,12 @@ static int epoll_wait_panic_fallback(int epfd, return epoll_wait(epfd, events, maxevents, timeout); } -#define epoll_wait epoll_wait_panic_fallback +#define epoll_create(_size) \ + epoll_create_panic_fallback(epoll_ev, _size) +#define epoll_ctl(_epfd, _op, _fd, _event) \ + epoll_ctl_panic_fallback(epoll_ev,_epfd, _op, _fd, _event) +#define epoll_wait(_epfd, _events, _maxevents, _timeout) \ + epoll_wait_panic_fallback(epoll_ev, _epfd, _events, _maxevents, _timeout) #endif /* -- 1.7.9.5 From 57d616c45ef4b39bc43d1519dd1d2d3cdbcb1b11 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 15 Feb 2013 16:33:56 +0100 Subject: [PATCH 06/34] tevent: avoid any operation on epoll_ev after a epoll_panic() This calls TALLOC_FREE(ev->additional_data), which is epoll_ev within epoll_panic() before calling the fallback handler. In order to notice that a epoll_panic() happened, a caller can register a pointer to a bool variable under epoll_ev->panic_state. As epoll_check_reopen() can fail due to a epoll_panic(), we need to force the replay flag if we have called any event handler. Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 85 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 11 deletions(-) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 3132367..8af8aac 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -40,6 +40,8 @@ struct epoll_event_context { pid_t pid; + bool panic_force_replay; + bool *panic_state; bool (*panic_fallback)(struct tevent_context *ev, bool replay); }; @@ -134,8 +136,21 @@ static void epoll_panic(struct epoll_event_context *epoll_ev, const char *reason, bool replay) { struct tevent_context *ev = epoll_ev->ev; + bool (*panic_fallback)(struct tevent_context *ev, bool replay); - if (epoll_ev->panic_fallback == NULL) { + panic_fallback = epoll_ev->panic_fallback; + + if (epoll_ev->panic_state != NULL) { + *epoll_ev->panic_state = true; + } + + if (epoll_ev->panic_force_replay) { + replay = true; + } + + TALLOC_FREE(ev->additional_data); + + if (panic_fallback == NULL) { tevent_debug(ev, TEVENT_DEBUG_FATAL, "%s (%s) replay[%u] - calling abort()\n", reason, strerror(errno), (unsigned)replay); @@ -146,7 +161,7 @@ static void epoll_panic(struct epoll_event_context *epoll_ev, "%s (%s) replay[%u] - calling panic_fallback\n", reason, strerror(errno), (unsigned)replay); - if (!epoll_ev->panic_fallback(ev, replay)) { + if (!panic_fallback(ev, replay)) { /* Fallback failed. */ tevent_debug(ev, TEVENT_DEBUG_FATAL, "%s (%s) replay[%u] - calling abort()\n", @@ -209,6 +224,8 @@ static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_ static void epoll_check_reopen(struct epoll_event_context *epoll_ev) { struct tevent_fd *fde; + bool *caller_panic_state = epoll_ev->panic_state; + bool panic_triggered = false; if (epoll_ev->pid == getpid()) { return; @@ -217,8 +234,7 @@ static void epoll_check_reopen(struct epoll_event_context *epoll_ev) close(epoll_ev->epoll_fd); epoll_ev->epoll_fd = epoll_create(64); if (epoll_ev->epoll_fd == -1) { - tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL, - "Failed to recreate epoll handle after fork\n"); + epoll_panic(epoll_ev, "epoll_create() failed", false); return; } @@ -228,9 +244,17 @@ static void epoll_check_reopen(struct epoll_event_context *epoll_ev) } epoll_ev->pid = getpid(); + epoll_ev->panic_state = &panic_triggered; for (fde=epoll_ev->ev->fd_events;fde;fde=fde->next) { epoll_add_event(epoll_ev, fde); + if (panic_triggered) { + if (caller_panic_state != NULL) { + *caller_panic_state = true; + } + return; + } } + epoll_ev->panic_state = NULL; } #define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT (1<<0) @@ -462,15 +486,33 @@ static int epoll_event_fd_destructor(struct tevent_fd *fde) { struct tevent_context *ev = fde->event_ctx; struct epoll_event_context *epoll_ev = NULL; + bool panic_triggered = false; - if (ev) { - epoll_ev = talloc_get_type(ev->additional_data, - struct epoll_event_context); + if (ev == NULL) { + return tevent_common_fd_destructor(fde); + } - epoll_check_reopen(epoll_ev); + epoll_ev = talloc_get_type_abort(ev->additional_data, + struct epoll_event_context); - epoll_del_event(epoll_ev, fde); + /* + * we must remove the event from the list + * otherwise a panic fallback handler may + * reuse invalid memory + */ + DLIST_REMOVE(ev->fd_events, fde); + + epoll_ev->panic_state = &panic_triggered; + epoll_check_reopen(epoll_ev); + if (panic_triggered) { + return tevent_common_fd_destructor(fde); + } + + epoll_del_event(epoll_ev, fde); + if (panic_triggered) { + return tevent_common_fd_destructor(fde); } + epoll_ev->panic_state = NULL; return tevent_common_fd_destructor(fde); } @@ -489,8 +531,7 @@ static struct tevent_fd *epoll_event_add_fd(struct tevent_context *ev, TALLOC_CT struct epoll_event_context *epoll_ev = talloc_get_type(ev->additional_data, struct epoll_event_context); struct tevent_fd *fde; - - epoll_check_reopen(epoll_ev); + bool panic_triggered = false; fde = tevent_common_add_fd(ev, mem_ctx, fd, flags, handler, private_data, @@ -499,6 +540,13 @@ static struct tevent_fd *epoll_event_add_fd(struct tevent_context *ev, TALLOC_CT talloc_set_destructor(fde, epoll_event_fd_destructor); + epoll_ev->panic_state = &panic_triggered; + epoll_check_reopen(epoll_ev); + if (panic_triggered) { + return fde; + } + epoll_ev->panic_state = NULL; + epoll_add_event(epoll_ev, fde); return fde; @@ -511,6 +559,7 @@ static void epoll_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags) { struct tevent_context *ev; struct epoll_event_context *epoll_ev; + bool panic_triggered = false; if (fde->flags == flags) return; @@ -519,7 +568,12 @@ static void epoll_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags) fde->flags = flags; + epoll_ev->panic_state = &panic_triggered; epoll_check_reopen(epoll_ev); + if (panic_triggered) { + return; + } + epoll_ev->panic_state = NULL; epoll_change_event(epoll_ev, fde); } @@ -532,6 +586,7 @@ 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 timeval tval; + bool panic_triggered = false; if (ev->signal_events && tevent_common_check_signal(ev)) { @@ -548,7 +603,15 @@ static int epoll_event_loop_once(struct tevent_context *ev, const char *location return 0; } + epoll_ev->panic_state = &panic_triggered; + epoll_ev->panic_force_replay = true; epoll_check_reopen(epoll_ev); + if (panic_triggered) { + errno = EINVAL; + return -1; + } + epoll_ev->panic_force_replay = false; + epoll_ev->panic_state = NULL; return epoll_event_loop(epoll_ev, &tval); } -- 1.7.9.5 From 3738a015987b59f8ff7fa0e00225e863ccb82f20 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 17 Feb 2013 23:21:28 +0100 Subject: [PATCH 07/34] tevent: don't skip a fd event if the previous one was deleted during poll() In a threaded environment it can happen that an tevent_fd is talloc_free'ed while the main thread sleeps in the poll() syscall. In such a case poll_event_fd_destructor() would set poll_ev->fdes[i] = NULL. We then skip the removed event, but before we also skipped the one that was located at the end of the array. We moved it to possition 'i', but the next loop uses 'i=i+1'. Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent_poll.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/tevent/tevent_poll.c b/lib/tevent/tevent_poll.c index 81a7176..68885e9 100644 --- a/lib/tevent/tevent_poll.c +++ b/lib/tevent/tevent_poll.c @@ -443,7 +443,7 @@ static int poll_event_loop_poll(struct tevent_context *ev, int pollrtn; int timeout = -1; unsigned first_fd; - unsigned i; + unsigned i, next_i; int poll_errno; if (ev->signal_events && tevent_common_check_signal(ev)) { @@ -490,11 +490,13 @@ static int poll_event_loop_poll(struct tevent_context *ev, which ones and call the handler, being careful to allow the handler to remove itself when called */ - for (i=first_fd; inum_fds; i++) { + for (i=first_fd; inum_fds; i = next_i) { struct pollfd *pfd; struct tevent_fd *fde; uint16_t flags = 0; + next_i = i + 1; + fde = poll_ev->fdes[i]; if (fde == NULL) { /* @@ -502,11 +504,16 @@ static int poll_event_loop_poll(struct tevent_context *ev, * from the arrays */ poll_ev->num_fds -= 1; + if (poll_ev->num_fds == i) { + break; + } poll_ev->fds[i] = poll_ev->fds[poll_ev->num_fds]; poll_ev->fdes[i] = poll_ev->fdes[poll_ev->num_fds]; if (poll_ev->fdes[i] != NULL) { poll_ev->fdes[i]->additional_flags = i; } + /* we have to reprocess position 'i' */ + next_i = i; continue; } -- 1.7.9.5 From 4ca73bf7f6a8ada616856f4beadeb8b01c821a31 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 17 Feb 2013 16:40:20 +0100 Subject: [PATCH 08/34] tevent: don't call TALLOC_FREE(ev->additional_data) in std_fallback_to_poll() The epoll backend has done the cleanup already. Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent_standard.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/tevent/tevent_standard.c b/lib/tevent/tevent_standard.c index d7a5bd7..a9c6170 100644 --- a/lib/tevent/tevent_standard.c +++ b/lib/tevent/tevent_standard.c @@ -68,7 +68,6 @@ static bool std_fallback_to_poll(struct tevent_context *ev, bool replay) /* First switch all the ops to poll. */ glue->epoll_ops = NULL; - TALLOC_FREE(ev->additional_data); /* * Set custom_ops the same as poll. -- 1.7.9.5 From 3be8dfcc20e560c9e72686d0354ea4da9f04e33a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 17 Feb 2013 16:41:41 +0100 Subject: [PATCH 09/34] tevent: add std_event_loop_wait() We also need to fallback in tevent_loop_wait() otherwise we might miss events in the poll->fresh list. Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent_standard.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/tevent/tevent_standard.c b/lib/tevent/tevent_standard.c index a9c6170..2584994 100644 --- a/lib/tevent/tevent_standard.c +++ b/lib/tevent/tevent_standard.c @@ -127,6 +127,22 @@ static int std_event_loop_once(struct tevent_context *ev, const char *location) return glue->poll_ops->loop_once(ev, location); } +static int std_event_loop_wait(struct tevent_context *ev, const char *location) +{ + void *glue_ptr = talloc_parent(ev->ops); + struct std_event_glue *glue = + talloc_get_type_abort(glue_ptr, + struct std_event_glue); + int ret; + + ret = glue->epoll_ops->loop_wait(ev, location); + if (glue->epoll_ops != NULL) { + /* No fallback */ + return ret; + } + + return glue->poll_ops->loop_wait(ev, location); +} /* Initialize the epoll backend and allow it to call a switch function if epoll fails at runtime. @@ -183,6 +199,7 @@ static int std_event_context_init(struct tevent_context *ev) *glue->glue_ops = *glue->epoll_ops; glue->glue_ops->context_init = std_event_context_init; glue->glue_ops->loop_once = std_event_loop_once; + glue->glue_ops->loop_wait = std_event_loop_wait; ret = glue->epoll_ops->context_init(ev); if (ret == -1) { -- 1.7.9.5 From f73cbb7cd20c8e5016d4ca27cda2bb86e27a1f1d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Feb 2013 13:07:34 +0100 Subject: [PATCH 10/34] tevent: remove unused if (epoll_ev->epoll_fd == -1) return; checks We'll never leave epoll_check_reopen() with epoll_fd == -1. Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 8af8aac..e22ea5d 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -268,8 +268,6 @@ static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_ { struct epoll_event event; - if (epoll_ev->epoll_fd == -1) return; - fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; /* if we don't want events yet, don't add an epoll_event */ @@ -297,8 +295,6 @@ static void epoll_del_event(struct epoll_event_context *epoll_ev, struct tevent_ { struct epoll_event event; - if (epoll_ev->epoll_fd == -1) return; - fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; /* if there's no epoll_event, we don't need to delete it */ @@ -320,7 +316,6 @@ static void epoll_del_event(struct epoll_event_context *epoll_ev, struct tevent_ static void epoll_mod_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde) { struct epoll_event event; - if (epoll_ev->epoll_fd == -1) return; fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; @@ -344,8 +339,6 @@ static void epoll_change_event(struct epoll_event_context *epoll_ev, struct teve bool want_read = (fde->flags & TEVENT_FD_READ); bool want_write= (fde->flags & TEVENT_FD_WRITE); - if (epoll_ev->epoll_fd == -1) return; - fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; /* there's already an event */ @@ -382,8 +375,6 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval int timeout = -1; int wait_errno; - if (epoll_ev->epoll_fd == -1) return -1; - if (tvalp) { /* it's better to trigger timed events a bit later than to early */ timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000); -- 1.7.9.5 From 7e2a8c51bd00fc958165389079e151ec4bcc08d9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Feb 2013 13:12:27 +0100 Subject: [PATCH 11/34] tevent: use helper variables to hold the epoll_ctl() result Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index e22ea5d..8cb690d 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -267,6 +267,7 @@ static void epoll_check_reopen(struct epoll_event_context *epoll_ev) static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde) { struct epoll_event event; + int ret; fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; @@ -276,7 +277,8 @@ static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_ ZERO_STRUCT(event); event.events = epoll_map_flags(fde->flags); event.data.ptr = fde; - if (epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event) != 0) { + ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event); + if (ret != 0) { epoll_panic(epoll_ev, "EPOLL_CTL_ADD failed", false); return; } @@ -294,6 +296,7 @@ static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_ static void epoll_del_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde) { struct epoll_event event; + int ret; fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; @@ -303,7 +306,8 @@ static void epoll_del_event(struct epoll_event_context *epoll_ev, struct tevent_ ZERO_STRUCT(event); event.events = epoll_map_flags(fde->flags); event.data.ptr = fde; - if (epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event) != 0) { + ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event); + if (ret != 0) { epoll_panic(epoll_ev, "EPOLL_CTL_DEL failed", false); return; } @@ -316,13 +320,15 @@ static void epoll_del_event(struct epoll_event_context *epoll_ev, struct tevent_ static void epoll_mod_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde) { struct epoll_event event; + int ret; fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; ZERO_STRUCT(event); event.events = epoll_map_flags(fde->flags); event.data.ptr = fde; - if (epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) { + ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event); + if (ret != 0) { epoll_panic(epoll_ev, "EPOLL_CTL_MOD failed", false); return; } -- 1.7.9.5 From 131df1d7408395a53b8437a5c8dd8e876547b16d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Feb 2013 17:15:52 +0100 Subject: [PATCH 12/34] tevent: the content of event is ignored by EPOLL_CTL_DEL Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 8cb690d..4a81c01 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -304,8 +304,6 @@ static void epoll_del_event(struct epoll_event_context *epoll_ev, struct tevent_ if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT)) return; ZERO_STRUCT(event); - event.events = epoll_map_flags(fde->flags); - event.data.ptr = fde; ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event); if (ret != 0) { epoll_panic(epoll_ev, "EPOLL_CTL_DEL failed", false); -- 1.7.9.5 From c4cb4031a950a9e356f13dd27c82be2c04e9ee24 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Feb 2013 12:55:11 +0100 Subject: [PATCH 13/34] tevent: s/epoll_change_event/epoll_update_event Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 4a81c01..c633a6e 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -337,7 +337,7 @@ static void epoll_mod_event(struct epoll_event_context *epoll_ev, struct tevent_ } } -static void epoll_change_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde) +static void epoll_update_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde) { bool got_error = (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR); bool want_read = (fde->flags & TEVENT_FD_READ); @@ -570,7 +570,7 @@ static void epoll_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags) } epoll_ev->panic_state = NULL; - epoll_change_event(epoll_ev, fde); + epoll_update_event(epoll_ev, fde); } /* -- 1.7.9.5 From f80a528d26b03a8b70a087e59e4d660d680b9062 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Feb 2013 11:26:00 +0100 Subject: [PATCH 14/34] tevent: always go through epoll_change_event() Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index c633a6e..760ea22 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -45,6 +45,10 @@ struct epoll_event_context { bool (*panic_fallback)(struct tevent_context *ev, bool replay); }; +#define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT (1<<0) +#define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1) +#define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2) + #ifdef TEST_PANIC_FALLBACK static int epoll_create_panic_fallback(struct epoll_event_context *epoll_ev, @@ -214,7 +218,7 @@ static int epoll_init_ctx(struct epoll_event_context *epoll_ev) return 0; } -static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde); +static void epoll_update_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde); /* reopen the epoll handle when our pid changes @@ -246,7 +250,9 @@ static void epoll_check_reopen(struct epoll_event_context *epoll_ev) epoll_ev->pid = getpid(); epoll_ev->panic_state = &panic_triggered; for (fde=epoll_ev->ev->fd_events;fde;fde=fde->next) { - epoll_add_event(epoll_ev, fde); + fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + epoll_update_event(epoll_ev, fde); + if (panic_triggered) { if (caller_panic_state != NULL) { *caller_panic_state = true; @@ -257,10 +263,6 @@ static void epoll_check_reopen(struct epoll_event_context *epoll_ev) epoll_ev->panic_state = NULL; } -#define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT (1<<0) -#define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1) -#define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2) - /* add the epoll event to the given fd_event */ @@ -429,7 +431,7 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval * to match the select() behavior */ if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) { - epoll_del_event(epoll_ev, fde); + epoll_update_event(epoll_ev, fde); continue; } flags |= TEVENT_FD_READ; @@ -482,6 +484,7 @@ static int epoll_event_fd_destructor(struct tevent_fd *fde) struct tevent_context *ev = fde->event_ctx; struct epoll_event_context *epoll_ev = NULL; bool panic_triggered = false; + int flags = fde->flags; if (ev == NULL) { return tevent_common_fd_destructor(fde); @@ -503,7 +506,9 @@ static int epoll_event_fd_destructor(struct tevent_fd *fde) return tevent_common_fd_destructor(fde); } - epoll_del_event(epoll_ev, fde); + fde->flags = 0; + epoll_update_event(epoll_ev, fde); + fde->flags = flags; if (panic_triggered) { return tevent_common_fd_destructor(fde); } @@ -542,7 +547,7 @@ static struct tevent_fd *epoll_event_add_fd(struct tevent_context *ev, TALLOC_CT } epoll_ev->panic_state = NULL; - epoll_add_event(epoll_ev, fde); + epoll_update_event(epoll_ev, fde); return fde; } -- 1.7.9.5 From 7d6472357aeddb5c2ba26b59dbc54fd811351ca4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Feb 2013 17:38:10 +0100 Subject: [PATCH 15/34] tevent: unify handling of HAS_EVENT and REPORT_ERROR in epoll_{add,mod,del}_event() epoll_{add,mod,del}_event() are only called via epoll_update_event() and epoll_update_event() should not remove REPORT_ERROR itself. Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 760ea22..e04a0ab2 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -271,11 +271,9 @@ static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_ struct epoll_event event; int ret; + fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; - /* if we don't want events yet, don't add an epoll_event */ - if (fde->flags == 0) return; - ZERO_STRUCT(event); event.events = epoll_map_flags(fde->flags); event.data.ptr = fde; @@ -284,8 +282,8 @@ static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_ epoll_panic(epoll_ev, "EPOLL_CTL_ADD failed", false); return; } - fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; /* only if we want to read we want to tell the event handler about errors */ if (fde->flags & TEVENT_FD_READ) { fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; @@ -300,18 +298,15 @@ static void epoll_del_event(struct epoll_event_context *epoll_ev, struct tevent_ struct epoll_event event; int ret; + fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; - /* if there's no epoll_event, we don't need to delete it */ - if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT)) return; - ZERO_STRUCT(event); ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event); if (ret != 0) { epoll_panic(epoll_ev, "EPOLL_CTL_DEL failed", false); return; } - fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; } /* @@ -322,6 +317,7 @@ static void epoll_mod_event(struct epoll_event_context *epoll_ev, struct tevent_ struct epoll_event event; int ret; + fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; ZERO_STRUCT(event); @@ -333,6 +329,7 @@ static void epoll_mod_event(struct epoll_event_context *epoll_ev, struct tevent_ return; } + fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; /* only if we want to read we want to tell the event handler about errors */ if (fde->flags & TEVENT_FD_READ) { fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; @@ -345,8 +342,6 @@ static void epoll_update_event(struct epoll_event_context *epoll_ev, struct teve bool want_read = (fde->flags & TEVENT_FD_READ); bool want_write= (fde->flags & TEVENT_FD_WRITE); - fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; - /* there's already an event */ if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT) { if (want_read || (want_write && !got_error)) { -- 1.7.9.5 From ca77b5f1218306769aae645d35af9a827ac1aa3d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Feb 2013 13:33:19 +0100 Subject: [PATCH 16/34] TODO-TESTING tevent: ignore EBADF from EPOLL_CTL_DEL --- lib/tevent/tevent_epoll.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index e04a0ab2..6842dcf 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -303,7 +303,11 @@ static void epoll_del_event(struct epoll_event_context *epoll_ev, struct tevent_ ZERO_STRUCT(event); ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event); - if (ret != 0) { + if (ret != 0 && errno == EBADF) { + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_WARNING, + "EPOLL_CTL_DEL for fd[%d] ignoring EBADF\n", + fde->fd); + } else if (ret != 0) { epoll_panic(epoll_ev, "EPOLL_CTL_DEL failed", false); return; } -- 1.7.9.5 From 4d07084ae8eb485dcc8d6546a9591e531cb76843 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Feb 2013 13:34:07 +0100 Subject: [PATCH 17/34] TODO-TESTING tevent: ignore EBADF from EPOLL_CTL_ADD/MOD --- lib/tevent/tevent_epoll.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 6842dcf..6fee1c3 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -48,6 +48,7 @@ struct epoll_event_context { #define EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT (1<<0) #define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1) #define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2) +#define EPOLL_ADDITIONAL_FD_FLAG_EBADF (1<<3) #ifdef TEST_PANIC_FALLBACK @@ -278,7 +279,13 @@ static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_ event.events = epoll_map_flags(fde->flags); event.data.ptr = fde; ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event); - if (ret != 0) { + if (ret != 0 && errno == EBADF) { + fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_EBADF; + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_WARNING, + "EPOLL_CTL_ADD for fd[%d] ignoring EBADF\n", + fde->fd); + return; + } else if (ret != 0) { epoll_panic(epoll_ev, "EPOLL_CTL_ADD failed", false); return; } @@ -328,7 +335,13 @@ static void epoll_mod_event(struct epoll_event_context *epoll_ev, struct tevent_ event.events = epoll_map_flags(fde->flags); event.data.ptr = fde; ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event); - if (ret != 0) { + if (ret != 0 && errno == EBADF) { + fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_EBADF; + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_WARNING, + "EPOLL_CTL_MOD for fd[%d] ignoring EBADF\n", + fde->fd); + return; + } else if (ret != 0) { epoll_panic(epoll_ev, "EPOLL_CTL_MOD failed", false); return; } @@ -346,6 +359,10 @@ static void epoll_update_event(struct epoll_event_context *epoll_ev, struct teve bool want_read = (fde->flags & TEVENT_FD_READ); bool want_write= (fde->flags & TEVENT_FD_WRITE); + if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_EBADF) { + return; + } + /* there's already an event */ if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT) { if (want_read || (want_write && !got_error)) { -- 1.7.9.5 From 9516071ee7962a6830f5c653f8f81b0bd69008ac Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Feb 2013 13:50:56 -0800 Subject: [PATCH 18/34] tevent: Start to fix the epoll backend to support 2 fd events on the same fd correctly. Add a utility function epoll_add_multiplex_fd() and a new flag EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX. This will be called by epoll_add_event() to merge two fde events with the same file descriptor. Signed-off-by: Jeremy Allison Signed-off-by: Stefan Metzmacher Reviewed-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 93 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 6fee1c3..4cd5eba 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -4,7 +4,8 @@ main select loop and event handling - epoll implementation Copyright (C) Andrew Tridgell 2003-2005 - Copyright (C) Stefan Metzmacher 2005-2009 + Copyright (C) Stefan Metzmacher 2005-2013 + Copyright (C) Jeremy Allison 2013 ** NOTE! The following LGPL license applies to the tevent ** library. This does NOT imply that all of Samba is released @@ -49,6 +50,7 @@ struct epoll_event_context { #define EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR (1<<1) #define EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR (1<<2) #define EPOLL_ADDITIONAL_FD_FLAG_EBADF (1<<3) +#define EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX (1<<4) #ifdef TEST_PANIC_FALLBACK @@ -265,6 +267,95 @@ static void epoll_check_reopen(struct epoll_event_context *epoll_ev) } /* + epoll cannot add the same file descriptor twice, once + with read, once with write which is allowed by the + tevent backend. Multiplex the existing fde, flag it + as such so we can search for the correct fde on + event triggering. +*/ + +static int epoll_add_multiplex_fd(struct epoll_event_context *epoll_ev, + struct tevent_fd *add_fde) +{ + struct epoll_event event; + struct tevent_fd *mpx_fde; + int ret; + + /* Find the existing fde that caused the EEXIST error. */ + for (mpx_fde = epoll_ev->ev->fd_events; mpx_fde; mpx_fde = mpx_fde->next) { + if (mpx_fde->fd != add_fde->fd) { + continue; + } + + if (mpx_fde == add_fde) { + continue; + } + + break; + } + if (mpx_fde == NULL) { + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL, + "can't find multiplex fde for fd[%d]", + add_fde->fd); + return -1; + } + + if (mpx_fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* Logic error. Can't have more than 2 multiplexed fde's. */ + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL, + "multiplex fde for fd[%d] is already multiplexed\n", + mpx_fde->fd); + return -1; + } + + /* + * The multiplex fde must have the same fd, and also + * already have an epoll event attached. + */ + if (!(mpx_fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT)) { + /* Logic error. Can't have more than 2 multiplexed fde's. */ + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL, + "multiplex fde for fd[%d] has no event\n", + mpx_fde->fd); + return -1; + } + + /* Modify the orig_fde to add in the new flags. */ + ZERO_STRUCT(event); + event.events = epoll_map_flags(mpx_fde->flags); + event.events |= epoll_map_flags(add_fde->flags); + event.data.ptr = mpx_fde; + ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_MOD, mpx_fde->fd, &event); + if (ret != 0 && errno == EBADF) { + mpx_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_EBADF; + add_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_EBADF; + tevent_debug(epoll_ev->ev, TEVENT_DEBUG_WARNING, + "EPOLL_CTL_MOD for fd[%d] ignoring EBADF\n", + mpx_fde->fd); + } else if (ret != 0) { + return ret; + } + + /* + * Make each fde->additional_data pointers point at each other + * so we can look them up from each other. They are now paired. + */ + mpx_fde->additional_data = (struct tevent_fd *)add_fde; + add_fde->additional_data = (struct tevent_fd *)mpx_fde; + + /* Now flag both fde's as being multiplexed. */ + mpx_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX; + add_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX; + + /* we need to keep the GOT_ERROR flag */ + if (mpx_fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR) { + add_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR; + } + + return 0; +} + +/* add the epoll event to the given fd_event */ static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde) -- 1.7.9.5 From 09642c830d55936827f48f45d5c42e85701979a2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Feb 2013 17:14:52 +0100 Subject: [PATCH 19/34] tevent: handle multiplexed fde's in epoll_add_event() Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 4cd5eba..6f8c9d3 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -362,16 +362,31 @@ static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_ { struct epoll_event event; int ret; + struct tevent_fd *mpx_fde = NULL; fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; + if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) { + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + + mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; + } + ZERO_STRUCT(event); event.events = epoll_map_flags(fde->flags); + if (mpx_fde != NULL) { + event.events |= epoll_map_flags(mpx_fde->flags); + } event.data.ptr = fde; ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event); if (ret != 0 && errno == EBADF) { fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_EBADF; + if (mpx_fde != NULL) { + mpx_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_EBADF; + } tevent_debug(epoll_ev->ev, TEVENT_DEBUG_WARNING, "EPOLL_CTL_ADD for fd[%d] ignoring EBADF\n", fde->fd); @@ -386,6 +401,16 @@ static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_ if (fde->flags & TEVENT_FD_READ) { fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; } + + if (mpx_fde == NULL) { + return; + } + + mpx_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + /* only if we want to read we want to tell the event handler about errors */ + if (mpx_fde->flags & TEVENT_FD_READ) { + mpx_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; + } } /* -- 1.7.9.5 From 306ab1df2990a0f63b48570ee6418e238b2688f3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 15 Feb 2013 10:16:44 -0800 Subject: [PATCH 20/34] tevent: Fix up epoll_del_event to cope with deleting a multiplexed fde event. Signed-off-by: Jeremy Allison Signed-off-by: Stefan Metzmacher Reviewed-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 6f8c9d3..c52673e 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -420,10 +420,19 @@ static void epoll_del_event(struct epoll_event_context *epoll_ev, struct tevent_ { struct epoll_event event; int ret; + struct tevent_fd *mpx_fde = NULL; fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; + if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) { + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + + mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; + } + ZERO_STRUCT(event); ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event); if (ret != 0 && errno == EBADF) { -- 1.7.9.5 From 40898b43ce23f47bc0997470eca54cb8df8c930f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Feb 2013 14:14:50 -0800 Subject: [PATCH 21/34] tevent: Fix epoll_mod_event() to cope with modifying a multiplexed fde event. Signed-off-by: Jeremy Allison Signed-off-by: Stefan Metzmacher Reviewed-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index c52673e..f92273d 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -450,18 +450,37 @@ static void epoll_del_event(struct epoll_event_context *epoll_ev, struct tevent_ */ static void epoll_mod_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde) { + struct tevent_fd *mpx_fde = NULL; struct epoll_event event; int ret; fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; + if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* + * This is a multiplexed fde, we need to include both + * flags in the modified event. + */ + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + + mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; + } + ZERO_STRUCT(event); event.events = epoll_map_flags(fde->flags); + if (mpx_fde != NULL) { + event.events |= epoll_map_flags(mpx_fde->flags); + } event.data.ptr = fde; ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event); if (ret != 0 && errno == EBADF) { fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_EBADF; + if (mpx_fde != NULL) { + mpx_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_EBADF; + } tevent_debug(epoll_ev->ev, TEVENT_DEBUG_WARNING, "EPOLL_CTL_MOD for fd[%d] ignoring EBADF\n", fde->fd); @@ -476,6 +495,16 @@ static void epoll_mod_event(struct epoll_event_context *epoll_ev, struct tevent_ if (fde->flags & TEVENT_FD_READ) { fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; } + + if (mpx_fde == NULL) { + return; + } + + mpx_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + /* only if we want to read we want to tell the event handler about errors */ + if (mpx_fde->flags & TEVENT_FD_READ) { + mpx_fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; + } } static void epoll_update_event(struct epoll_event_context *epoll_ev, struct tevent_fd *fde) -- 1.7.9.5 From 0a69e6ea409c297ab2397b21c848694f9973f2c8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Feb 2013 18:01:57 +0100 Subject: [PATCH 22/34] tevent: handle multiplexed fde's in epoll_event_fd_destructor() Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index f92273d..6a994b7 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -670,12 +670,33 @@ static int epoll_event_fd_destructor(struct tevent_fd *fde) */ DLIST_REMOVE(ev->fd_events, fde); + if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) { + struct tevent_fd *mpx_fde = + talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + + fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX; + mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX; + + fde->additional_data = NULL; + mpx_fde->additional_data = NULL; + + fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT; + } + epoll_ev->panic_state = &panic_triggered; epoll_check_reopen(epoll_ev); if (panic_triggered) { return tevent_common_fd_destructor(fde); } + if (mpx_fde != NULL) { + epoll_update_event(epoll_ev, mpx_fde); + if (panic_triggered) { + return tevent_common_fd_destructor(fde); + } + } + fde->flags = 0; epoll_update_event(epoll_ev, fde); fde->flags = flags; -- 1.7.9.5 From 48b9c01b75794d1e4642f23f525ccd7af2e1776c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Feb 2013 17:17:31 +0100 Subject: [PATCH 23/34] tevent: handle EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX in epoll_update_event() Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 6a994b7..92aaf76 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -512,11 +512,29 @@ static void epoll_update_event(struct epoll_event_context *epoll_ev, struct teve bool got_error = (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR); bool want_read = (fde->flags & TEVENT_FD_READ); bool want_write= (fde->flags & TEVENT_FD_WRITE); + struct tevent_fd *mpx_fde = NULL; if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_EBADF) { return; } + if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) { + /* + * Save off the multiplexed event in case we need + * to use it to call the handler function. + */ + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + + if (mpx_fde->flags & TEVENT_FD_READ) { + want_read = true; + } + + if (mpx_fde->flags & TEVENT_FD_WRITE) { + want_write = true; + } + } + /* there's already an event */ if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT) { if (want_read || (want_write && !got_error)) { -- 1.7.9.5 From f4ddf002dec2e726ca44cd18050f24e1935d3f0c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Feb 2013 15:53:38 -0800 Subject: [PATCH 24/34] tevent: Add utility function epoll_handle_hup_or_err() We'll use this to handle the EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR and EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR flags with multiplexed events in the event loop. Signed-off-by: Jeremy Allison Reviewed-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 92aaf76..7acbe78 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -559,6 +559,38 @@ static void epoll_update_event(struct epoll_event_context *epoll_ev, struct teve } /* + Cope with epoll returning EPOLLHUP|EPOLLERR on an event. + Return true if there's nothing else to do, false if + this event needs further handling. +*/ +static bool epoll_handle_hup_or_err(struct epoll_event_context *epoll_ev, + struct tevent_fd *fde) +{ + if (fde == NULL) { + /* Nothing to do if no event. */ + return true; + } + + fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR; + /* + * if we only wait for TEVENT_FD_WRITE, we should not tell the + * event handler about it, and remove the epoll_event, + * as we only report errors when waiting for read events, + * to match the select() behavior + */ + if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) { + /* + * Do the same as the poll backend and + * remove the writeable flag. + */ + fde->flags &= ~TEVENT_FD_WRITE; + return true; + } + /* This has TEVENT_FD_READ set, we're not finished. */ + return false; +} + +/* event loop handling using epoll */ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval *tvalp) -- 1.7.9.5 From d8116b64adea07389ba3acd442c81ff112e79bf9 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Feb 2013 14:49:17 +0100 Subject: [PATCH 25/34] tevent: In epoll_event_loop() ensure we trigger the right handler for a multiplexed fde event. Signed-off-by: Jeremy Allison Signed-off-by: Stefan Metzmacher Reviewed-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 7acbe78..0382773 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -637,27 +637,51 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval struct tevent_fd *fde = talloc_get_type(events[i].data.ptr, struct tevent_fd); uint16_t flags = 0; + struct tevent_fd *mpx_fde = NULL; if (fde == NULL) { epoll_panic(epoll_ev, "epoll_wait() gave bad data", true); return -1; } - if (events[i].events & (EPOLLHUP|EPOLLERR)) { - fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR; + if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_MPX) { /* - * if we only wait for TEVENT_FD_WRITE, we should not tell the - * event handler about it, and remove the epoll_event, - * as we only report errors when waiting for read events, - * to match the select() behavior + * Save off the multiplexed event in case we need + * to use it to call the handler function. */ - if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) { + mpx_fde = talloc_get_type_abort(fde->additional_data, + struct tevent_fd); + } + if (events[i].events & (EPOLLHUP|EPOLLERR)) { + bool handled_fde = epoll_handle_hup_or_err(epoll_ev, fde); + bool handled_mpx = epoll_handle_hup_or_err(epoll_ev, mpx_fde); + + if (handled_fde && handled_mpx) { epoll_update_event(epoll_ev, fde); continue; } + + if (!handled_mpx) { + /* + * If the mpx event was the one that needs + * further handling, it's the TEVENT_FD_READ + * event so switch over and call that handler. + */ + fde = mpx_fde; + mpx_fde = NULL; + } flags |= TEVENT_FD_READ; } if (events[i].events & EPOLLIN) flags |= TEVENT_FD_READ; if (events[i].events & EPOLLOUT) flags |= TEVENT_FD_WRITE; + + if (mpx_fde) { + /* Ensure we got the right fde. */ + if ((flags & fde->flags) == 0) { + fde = mpx_fde; + mpx_fde = NULL; + } + } + if (flags) { fde->handler(epoll_ev->ev, fde, flags, fde->private_data); break; -- 1.7.9.5 From ed7a3884f9e4c8f1d2ea43aabcd7936b2c3547d4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Feb 2013 11:50:56 +0100 Subject: [PATCH 26/34] tevent: preferr the write handler in there're two possible handlers registered with epoll Signed-off-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 0382773..871e771 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -674,6 +674,16 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval if (events[i].events & EPOLLIN) flags |= TEVENT_FD_READ; if (events[i].events & EPOLLOUT) flags |= TEVENT_FD_WRITE; + if (flags & TEVENT_FD_WRITE) { + if (fde->flags & TEVENT_FD_WRITE) { + mpx_fde = NULL; + } + if (mpx_fde && mpx_fde->flags & TEVENT_FD_WRITE) { + fde = mpx_fde; + mpx_fde = NULL; + } + } + if (mpx_fde) { /* Ensure we got the right fde. */ if ((flags & fde->flags) == 0) { -- 1.7.9.5 From e43988c0fe853b6ae868104488b73aa1004d5633 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Feb 2013 13:52:41 -0800 Subject: [PATCH 27/34] tevent: If epoll_ctl(..EPOLL_CTL_ADD,..) failes with EEXIST, merge the two fde's into one epoll event. Signed-off-by: Jeremy Allison Signed-off-by: Stefan Metzmacher Reviewed-by: Stefan Metzmacher --- lib/tevent/tevent_epoll.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 871e771..0b8c4b8 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -391,6 +391,13 @@ static void epoll_add_event(struct epoll_event_context *epoll_ev, struct tevent_ "EPOLL_CTL_ADD for fd[%d] ignoring EBADF\n", fde->fd); return; + } else if (ret != 0 && errno == EEXIST && mpx_fde == NULL) { + ret = epoll_add_multiplex_fd(epoll_ev, fde); + if (ret != 0) { + epoll_panic(epoll_ev, "epoll_add_multiplex_fd failed", + false); + return; + } } else if (ret != 0) { epoll_panic(epoll_ev, "EPOLL_CTL_ADD failed", false); return; -- 1.7.9.5 From 98e1a9fb83d36880b23aecc14dbaaec386698b96 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 14 Feb 2013 14:16:31 -0800 Subject: [PATCH 28/34] TODO: Regression test to ensure that a tevent backend can cope with separate read/write events on a single fd. This tests the multiplex fd changes to the epoll backend to ensure they work correctly. Signed-off-by: Jeremy Allison TODO: why (fde_wcount - fde_count < 256) ??? if we get TEVENT_FD_WRITE we should not block we should also not read if we don't get TEVENT_FD_READ, because this will block --- lib/tevent/testsuite.c | 52 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/lib/tevent/testsuite.c b/lib/tevent/testsuite.c index 3d2a79a..a6ab583 100644 --- a/lib/tevent/testsuite.c +++ b/lib/tevent/testsuite.c @@ -4,6 +4,7 @@ testing of the events subsystem Copyright (C) Stefan Metzmacher 2006-2009 + Copyright (C) Jeremy Allison 2013 ** NOTE! The following LGPL license applies to the tevent ** library. This does NOT imply that all of Samba is released @@ -34,19 +35,26 @@ #endif static int fde_count; +static int fde_wcount; -static void fde_handler(struct tevent_context *ev_ctx, struct tevent_fd *f, +static void fde_handler_readwrite(struct tevent_context *ev_ctx, struct tevent_fd *f, uint16_t flags, void *private_data) { int *fd = (int *)private_data; - char c; + char c = 0; #ifdef SA_SIGINFO kill(getpid(), SIGUSR1); #endif kill(getpid(), SIGALRM); - read(fd[0], &c, 1); - write(fd[1], &c, 1); - fde_count++; + + if ((flags & TEVENT_FD_WRITE) && (fde_wcount - fde_count < 256)) { + /* Don't fill the pipe and block... */ + write(fd[1], &c, 1); + fde_wcount++; + } else { + read(fd[0], &c, 1); + fde_count++; + } } static void finished_handler(struct tevent_context *ev_ctx, struct tevent_timer *te, @@ -70,7 +78,10 @@ static bool test_event_context(struct torture_context *test, int fd[2] = { -1, -1 }; const char *backend = (const char *)test_data; int alarm_count=0, info_count=0; - struct tevent_fd *fde; + struct tevent_fd *fde_read; + struct tevent_fd *fde_read_1; + struct tevent_fd *fde_write; + struct tevent_fd *fde_write_1; #ifdef SA_RESTART struct tevent_signal *se1 = NULL; #endif @@ -80,7 +91,6 @@ static bool test_event_context(struct torture_context *test, #endif int finished=0; struct timeval t; - char c = 0; ev_ctx = tevent_context_init_byname(test, backend); if (ev_ctx == NULL) { @@ -92,13 +102,23 @@ static bool test_event_context(struct torture_context *test, /* reset globals */ fde_count = 0; + fde_wcount = 0; /* create a pipe */ pipe(fd); - fde = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_READ, - fde_handler, fd); - tevent_fd_set_auto_close(fde); + fde_read = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_READ, + fde_handler_readwrite, fd); + fde_write_1 = tevent_add_fd(ev_ctx, ev_ctx, fd[0], TEVENT_FD_WRITE, + fde_handler_readwrite, fd); + + fde_write = tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_WRITE, + fde_handler_readwrite, fd); + fde_read_1 = tevent_add_fd(ev_ctx, ev_ctx, fd[1], TEVENT_FD_READ, + fde_handler_readwrite, fd); + + tevent_fd_set_auto_close(fde_read); + tevent_fd_set_auto_close(fde_write); tevent_add_timer(ev_ctx, ev_ctx, timeval_current_ofs(2,0), finished_handler, &finished); @@ -113,8 +133,6 @@ static bool test_event_context(struct torture_context *test, se3 = tevent_add_signal(ev_ctx, ev_ctx, SIGUSR1, SA_SIGINFO, count_handler, &info_count); #endif - write(fd[1], &c, 1); - t = timeval_current(); while (!finished) { errno = 0; @@ -124,8 +142,10 @@ static bool test_event_context(struct torture_context *test, } } - talloc_free(fde); - close(fd[1]); + talloc_free(fde_read); + talloc_free(fde_write); + talloc_free(fde_read_1); + talloc_free(fde_write_1); while (alarm_count < fde_count+1) { if (tevent_loop_once(ev_ctx) == -1) { @@ -139,11 +159,11 @@ static bool test_event_context(struct torture_context *test, talloc_free(se1); #endif - torture_assert_int_equal(test, alarm_count, 1+fde_count, "alarm count mismatch"); + torture_assert_int_equal(test, alarm_count, 1+fde_count+fde_wcount, "alarm count mismatch"); #ifdef SA_SIGINFO talloc_free(se3); - torture_assert_int_equal(test, info_count, fde_count, "info count mismatch"); + torture_assert_int_equal(test, info_count, fde_count+fde_wcount, "info count mismatch"); #endif talloc_free(ev_ctx); -- 1.7.9.5 From dba6cf55cad6e4bc269b3d86a21945a90568a017 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Feb 2013 16:45:29 +0100 Subject: [PATCH 29/34] HACK tevent_standard no fallback --- lib/tevent/tevent_standard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tevent/tevent_standard.c b/lib/tevent/tevent_standard.c index 2584994..7a82414 100644 --- a/lib/tevent/tevent_standard.c +++ b/lib/tevent/tevent_standard.c @@ -205,7 +205,7 @@ static int std_event_context_init(struct tevent_context *ev) if (ret == -1) { goto fallback; } -#ifdef HAVE_EPOLL +#if 0 //def HAVE_EPOLL if (!tevent_epoll_set_panic_fallback(ev, std_fallback_to_poll)) { TALLOC_FREE(ev->additional_data); goto fallback; -- 1.7.9.5 From 08722d7f8bea462ebef11a5d385db8f40a1b42da Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Feb 2013 16:45:47 +0100 Subject: [PATCH 30/34] Revert "HACK tevent_standard no fallback" This reverts commit 6597a8f6fc9870cd02aa0650f4a0e3453d49f4cd. --- lib/tevent/tevent_standard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tevent/tevent_standard.c b/lib/tevent/tevent_standard.c index 7a82414..2584994 100644 --- a/lib/tevent/tevent_standard.c +++ b/lib/tevent/tevent_standard.c @@ -205,7 +205,7 @@ static int std_event_context_init(struct tevent_context *ev) if (ret == -1) { goto fallback; } -#if 0 //def HAVE_EPOLL +#ifdef HAVE_EPOLL if (!tevent_epoll_set_panic_fallback(ev, std_fallback_to_poll)) { TALLOC_FREE(ev->additional_data); goto fallback; -- 1.7.9.5 From bc49a53df008c48a1b0bd37faf83454bd9f33f04 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 17 Feb 2013 16:43:49 +0100 Subject: [PATCH 31/34] HACK epoll TEST_PANIC_FALLBACK --- lib/tevent/tevent_epoll.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index 0b8c4b8..b2e1089 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -32,6 +32,8 @@ #include "tevent_internal.h" #include "tevent_util.h" +#define TEST_PANIC_FALLBACK + struct epoll_event_context { /* a pointer back to the generic event_context */ struct tevent_context *ev; -- 1.7.9.5 From d667a7f9037754781d4a2d21a479f0effb6f6382 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 20 Feb 2013 15:12:08 +0100 Subject: [PATCH 32/34] Revert "HACK epoll TEST_PANIC_FALLBACK" This reverts commit 0b9c1ee06465ba0edd0753a3b6b526fa045288a3. --- lib/tevent/tevent_epoll.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c index b2e1089..0b8c4b8 100644 --- a/lib/tevent/tevent_epoll.c +++ b/lib/tevent/tevent_epoll.c @@ -32,8 +32,6 @@ #include "tevent_internal.h" #include "tevent_util.h" -#define TEST_PANIC_FALLBACK - struct epoll_event_context { /* a pointer back to the generic event_context */ struct tevent_context *ev; -- 1.7.9.5 From b7098a74626e939f5e0109274c8f92f47cb5bfe1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 31 Jan 2013 14:35:57 +0100 Subject: [PATCH 33/34] TESTING ONLY: tevent: Force the poll backend --- lib/tevent/tevent.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c index 3b273d6..28ea995 100644 --- a/lib/tevent/tevent.c +++ b/lib/tevent/tevent.c @@ -140,6 +140,7 @@ _PRIVATE_ const struct tevent_ops *tevent_find_ops_byname(const char *name) } if (name == NULL) { name = "standard"; + name = "poll"; } for (e = tevent_backends; e != NULL; e = e->next) { -- 1.7.9.5 From 8c7e0128ff87781581992608708c8bcae6274bea Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 14 Feb 2013 12:28:28 +0100 Subject: [PATCH 34/34] Revert "TESTING ONLY: tevent: Force the poll backend" This reverts commit 81485d356d19a97adb84d8db981c679a8afa3c54. --- lib/tevent/tevent.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/tevent/tevent.c b/lib/tevent/tevent.c index 28ea995..3b273d6 100644 --- a/lib/tevent/tevent.c +++ b/lib/tevent/tevent.c @@ -140,7 +140,6 @@ _PRIVATE_ const struct tevent_ops *tevent_find_ops_byname(const char *name) } if (name == NULL) { name = "standard"; - name = "poll"; } for (e = tevent_backends; e != NULL; e = e->next) { -- 1.7.9.5