[PATCH] Fix epoll backend to allow separate read/write events on one fd.
Jeremy Allison
jra at samba.org
Thu Feb 14 21:09:07 MST 2013
On Thu, Feb 14, 2013 at 04:40:49PM -0800, Jeremy Allison wrote:
>
> Ok, *now* I've seem the bug here. Will fix and re-post
> and ammeded fix tomorrow.
Ok, third time lucky :-).
Here is a patchset that addresses the following 3 things:
1). Correctly handles the EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR
and EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR in the loop code.
2). Ensures EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT is set/cleared
correctly (this was the bug I missed in the previous patchset).
3). Uses fde->addtitional_data to store a pointer to the
multiplex pair event, saving a list traverse.
Passes test here. Please review and push if you're
happy with it.
Cheers,
Jeremy.
Previous text follows so everything is in one email.
---------------------------------------------------
On Thu, Feb 14, 2013 at 03:18:27PM +0100, Stefan (metze) Metzmacher wrote:
> I see the protection against more than two handlers.
I think you mean "don't see the protection against", yes ?
I've made it clearer where the protection is - having
more than 2 handlers is treated internally as a logic
error.
Note this doesn't cope with the case where the same
fd is added multiple times with a flags==0, and then
tevent_fd_set_flags() is called multiple times to turn
on flags on all the events, but then again neither does
the original epoll backend code.
Fixing that I think should be an additional patch
(after this patchset) that adds the 'no more than
two handlers per-fd, one read, one write, or one
handler with read+write' restriction on all the tevent
backends, so isn't part of this patch.
> The tricky part is the EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR
> and EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR. I don't think that's
> handled correct in your patches.
Ok, I have looked really carefully at this, and I found
what (I hope :-) you were referring to and have fixed it.
Essentially once epoll_wait returns EPOLLHUP|EPOLLERR
I need to ensure both paired fde events are handled
correctly, by removing the event that has TEVENT_FD_WRITE
set, and then ensuring the handler is called for
the paired event with TEVENT_FD_READ set.
I now handle that case correctly, but check the new
code inside epoll_event_loop() to be sure !
> I'm also not sure if the EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT is filled
> and cleared correctly.
Ok, I think I've found the bug here in epoll_del_event()
and fixed it. Please check.
> Can you change the code to store the pointer to the other event
> in fde->addtitional_data toghether with the
> EPOLL_ADDITIONAL_FD_WAS_MULTIPLEXED
> flag? That would avoid a list traverse for a lot of cases.
Done - great idea and made the code simpler, thanks !
> We need a destructor that removes the cross-reference on delete.
That's done in the epoll_del_event code (it removes the
cross reference when it un-pairs a paired set of events).
When deleting the event itself it doesn't matter (memory will
be freed anyway) and in the fallback code from epoll->poll
the poll code already overwrites the additional_flags and
additional_data fields.
> This way we can preferr the write handler over the read handler
> and also make sure that tevent_fd_set_flags doesn't set the same flag
> to both handlers.
ESCOPE :-). Not in the scope of this patchset. Let's
add it on top after you've reviewed this one.
> It would be good to enforce the rule of just one fd event for
> TEVENT_FD_READ and just one fd event for TEVENT_FD_WRITE.
> We need to enforce this on tevent_add_fd() and on tevent_fd_set_flags()
> and for all backends.
ESCOPE again.. :-).
> It's good to get this finally fixed, thanks!
You're welcome !
---------------------------------------------------
-------------- next part --------------
From a67c7d24aaf925aa5066570e466664631fce1078 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 14 Feb 2013 13:50:56 -0800
Subject: [PATCH 1/7] Start to fix the epoll backend to support 2 fd events on
the same fd correctly.
Add a utility function epoll_add_duplicate_fd() and
a new flag EPOLL_ADDITIONAL_FD_WAS_MULTIPLEXED.
This will be called by epoll_add_event() to merge two
fde events with the same file descriptor.
Signed-off-by: Jeremy Allison <jra at samba.org>
---
lib/tevent/tevent_epoll.c | 67 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 67 insertions(+)
diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c
index 8696215..8344d9d 100644
--- a/lib/tevent/tevent_epoll.c
+++ b/lib/tevent/tevent_epoll.c
@@ -5,6 +5,7 @@
Copyright (C) Andrew Tridgell 2003-2005
Copyright (C) Stefan Metzmacher 2005-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
@@ -192,6 +193,72 @@ static void epoll_check_reopen(struct epoll_event_context *epoll_ev)
#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_WAS_MULTIPLEXED (1<<3)
+
+/*
+ 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_duplicate_fd(struct epoll_event_context *epoll_ev,
+ struct tevent_fd *add_fde)
+{
+ struct epoll_event event;
+ struct tevent_fd *orig_fde;
+ int ret;
+
+ /* Find the existing fde that caused the EEXIST error. */
+ for (orig_fde = epoll_ev->ev->fd_events; orig_fde; orig_fde = orig_fde->next) {
+ if (orig_fde == add_fde) {
+ continue;
+ }
+ /*
+ * The multiplex fde must have the same fd, and also
+ * already have an epoll event attached.
+ */
+ if (orig_fde->fd == add_fde->fd &&
+ (orig_fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT)) {
+ break;
+ }
+ }
+ if (orig_fde == NULL) {
+ tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL,
+ "can't find multiplex fde");
+ return -1;
+ }
+
+ if (orig_fde->additional_flags & EPOLL_ADDITIONAL_FD_WAS_MULTIPLEXED) {
+ /* Logic error. Can't have more than 2 multiplexed fde's. */
+ tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL,
+ "multiplex fde has bad additional_flags");
+ return -1;
+ }
+
+ /* Modify the orig_fde to add in the new flags. */
+ ZERO_STRUCT(event);
+ event.events = epoll_map_flags(orig_fde->flags) |
+ epoll_map_flags(add_fde->flags);
+ event.data.ptr = orig_fde;
+ ret = epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_MOD, orig_fde->fd, &event);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* Now flag both fde's as being multiplexed. */
+ orig_fde->additional_flags |= EPOLL_ADDITIONAL_FD_WAS_MULTIPLEXED;
+ add_fde->additional_flags |= EPOLL_ADDITIONAL_FD_WAS_MULTIPLEXED;
+ /*
+ * Make each fde->additional_data pointers point at each other
+ * so we can look them up from each other. They are now paired.
+ */
+ orig_fde->additional_data = (struct tevent_fd *)add_fde;
+ add_fde->additional_data = (struct tevent_fd *)orig_fde;
+
+ return 0;
+}
/*
add the epoll event to the given fd_event
--
1.7.10.4
From ed228a681ed0e91bb9c808dbc8cef93e72fe8357 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 14 Feb 2013 13:52:41 -0800
Subject: [PATCH 2/7] If epoll_ctl(..EPOLL_CTL_ADD,..) failes with EEXIST,
merge the two fde's into one epoll event.
Signed-off-by: Jeremy Allison <jra at samba.org>
---
lib/tevent/tevent_epoll.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c
index 8344d9d..e47b823 100644
--- a/lib/tevent/tevent_epoll.c
+++ b/lib/tevent/tevent_epoll.c
@@ -278,8 +278,16 @@ static void epoll_add_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_ADD, fde->fd, &event) != 0) {
- epoll_panic(epoll_ev, "EPOLL_CTL_ADD failed", false);
- return;
+ if (errno == EEXIST) {
+ if (epoll_add_duplicate_fd(epoll_ev, fde) != 0) {
+ epoll_panic(epoll_ev, "epoll_add_duplicate_fd "
+ "failed", false);
+ return;
+ }
+ } else {
+ epoll_panic(epoll_ev, "EPOLL_CTL_ADD failed", false);
+ return;
+ }
}
fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
--
1.7.10.4
From 78cb102acba87f7addb424918a7e43f1a558dfd1 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 14 Feb 2013 14:13:05 -0800
Subject: [PATCH 3/7] Fix up epoll_del_event to cope with deleting a
multiplexed fde event.
Signed-off-by: Jeremy Allison <jra at samba.org>
---
lib/tevent/tevent_epoll.c | 43 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 38 insertions(+), 5 deletions(-)
diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c
index e47b823..9919789 100644
--- a/lib/tevent/tevent_epoll.c
+++ b/lib/tevent/tevent_epoll.c
@@ -303,6 +303,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 op = EPOLL_CTL_DEL;
if (epoll_ev->epoll_fd == -1) return;
@@ -311,15 +312,47 @@ static void epoll_del_event(struct epoll_event_context *epoll_ev, struct tevent_
/* if there's no epoll_event, we don't need to delete it */
if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT)) return;
+ /* Ensure we remove the flag on the correct event, even if paired. */
+ fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
+
+ if (fde->additional_flags & EPOLL_ADDITIONAL_FD_WAS_MULTIPLEXED) {
+ /*
+ * If this is a multiplexed fde, we need to replace it
+ * with the remaining paired event.
+ */
+ struct tevent_fd *mpx_fde = (struct tevent_fd *)fde->additional_data;
+ if (mpx_fde == NULL) {
+ epoll_panic(epoll_ev, "fde->additional_data==NULL", false);
+ return;
+ }
+ /* Remove multiplexed flag from both events. */
+ fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_WAS_MULTIPLEXED;
+ mpx_fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_WAS_MULTIPLEXED;
+ /* And unpair the two events. */
+ fde->additional_data = NULL;
+ mpx_fde->additional_data = NULL;
+
+ /* Modify, don't delete the remaining event. */
+ op = EPOLL_CTL_MOD;
+ fde = mpx_fde;
+ }
+
ZERO_STRUCT(event);
event.events = epoll_map_flags(fde->flags);
event.data.ptr = fde;
- if (epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event) != 0) {
- tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL,
- "epoll_del_event failed! probable early close bug (%s)\n",
- strerror(errno));
+ if (epoll_ctl(epoll_ev->epoll_fd, op, fde->fd, &event) != 0) {
+ if (op == EPOLL_CTL_DEL) {
+ tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL,
+ "EPOLL_CTL_DEL failed. probable early close bug (%s)\n",
+ strerror(errno));
+ } else {
+ tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL,
+ "failed changing mpx fd (%s)\n",
+ strerror(errno));
+ epoll_panic(epoll_ev, "EPOLL_CTL_MOD failed", false);
+ return;
+ }
}
- fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT;
}
/*
--
1.7.10.4
From bc6cfeec67aacc52c4db21ef5ed49087ea6bc49c Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 14 Feb 2013 14:14:50 -0800
Subject: [PATCH 4/7] Fix epoll_mod_event() to cope with modifying a
multiplexed fde event.
Signed-off-by: Jeremy Allison <jra at samba.org>
---
lib/tevent/tevent_epoll.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c
index 9919789..ea358b4 100644
--- a/lib/tevent/tevent_epoll.c
+++ b/lib/tevent/tevent_epoll.c
@@ -367,6 +367,18 @@ static void epoll_mod_event(struct epoll_event_context *epoll_ev, struct tevent_
ZERO_STRUCT(event);
event.events = epoll_map_flags(fde->flags);
+ if (fde->additional_flags & EPOLL_ADDITIONAL_FD_WAS_MULTIPLEXED) {
+ /*
+ * This is a multiplexed fde, we need to include both
+ * flags in the modified event.
+ */
+ struct tevent_fd *mpx_fde = (struct tevent_fd *)fde->additional_data;
+ if (mpx_fde == NULL) {
+ epoll_panic(epoll_ev, "fde->additional_data==NULL", false);
+ return;
+ }
+ event.events |= epoll_map_flags(mpx_fde->flags);
+ }
event.data.ptr = fde;
if (epoll_ctl(epoll_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) {
epoll_panic(epoll_ev, "EPOLL_CTL_MOD failed", false);
--
1.7.10.4
From 2445ac4896f4c71100473bd841c72af7ceb6ece7 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 14 Feb 2013 15:53:38 -0800
Subject: [PATCH 5/7] 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 <jra at samba.org>
---
lib/tevent/tevent_epoll.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c
index ea358b4..b75ff59 100644
--- a/lib/tevent/tevent_epoll.c
+++ b/lib/tevent/tevent_epoll.c
@@ -425,6 +425,37 @@ static void epoll_change_event(struct epoll_event_context *epoll_ev, struct teve
}
/*
+ Cope with epoll returning EPOLLHUP|EPOLLERR on an event.
+ Return true if there's nothing else to do, false if
+ this event needs further handling.
+*/
+static bool epoll_handle_hup_or_err(struct epoll_event_context *epoll_ev,
+ struct tevent_fd *fde)
+{
+ if (fde == NULL) {
+ /* Nothing to do if no event. */
+ return true;
+ }
+
+ fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR;
+ /*
+ * if we only wait for TEVENT_FD_WRITE, we should not tell the
+ * event handler about it, and remove the epoll_event,
+ * as we only report errors when waiting for read events,
+ * to match the select() behavior
+ */
+ if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) {
+ epoll_del_event(epoll_ev, fde);
+ /* 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.10.4
From 8e1ba4f49aa0a4f43d594e615e85f30d72b4b384 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 14 Feb 2013 15:59:40 -0800
Subject: [PATCH 6/7] In epoll_event_loop() ensure we trigger the right
handler for a multiplexed fde event.
Signed-off-by: Jeremy Allison <jra at samba.org>
---
lib/tevent/tevent_epoll.c | 38 ++++++++++++++++++++++++++++++--------
1 file changed, 30 insertions(+), 8 deletions(-)
diff --git a/lib/tevent/tevent_epoll.c b/lib/tevent/tevent_epoll.c
index b75ff59..ed1a113 100644
--- a/lib/tevent/tevent_epoll.c
+++ b/lib/tevent/tevent_epoll.c
@@ -502,27 +502,49 @@ 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_WAS_MULTIPLEXED) {
/*
- * if we only wait for TEVENT_FD_WRITE, we should not tell the
- * event handler about it, and remove the epoll_event,
- * as we only report errors when waiting for read events,
- * to match the select() behavior
+ * Save off the multiplexed event in case we need
+ * to use it to call the handler function.
*/
- if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) {
- epoll_del_event(epoll_ev, fde);
+ mpx_fde = (struct tevent_fd *)fde->additional_data;
+ if (mpx_fde == NULL) {
+ epoll_panic(epoll_ev, "logic error", true);
+ return -1;
+ }
+ }
+ 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) {
+ /* Fully dealt with this event. */
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;
+ }
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;
+ }
+ }
if (flags) {
fde->handler(epoll_ev->ev, fde, flags, fde->private_data);
break;
--
1.7.10.4
From fe160b71f47ab9e2a874196237ae8e629d4285de Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Thu, 14 Feb 2013 14:16:31 -0800
Subject: [PATCH 7/7] 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 <jra at samba.org>
---
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.10.4
More information about the samba-technical
mailing list