summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2013-02-28 17:07:28 +0100
committerJeremy Allison <jra@samba.org>2013-03-01 11:59:42 -0800
commitf45abeae40495460e29347ebc3c73b9ffece847d (patch)
tree7ace1cb67180959eb3d08c74152c7b23e7db2aa7
parentef8130fdbf50384dca3669ab27de4863490d5cb1 (diff)
downloadsamba-f45abeae40495460e29347ebc3c73b9ffece847d.tar.gz
samba-f45abeae40495460e29347ebc3c73b9ffece847d.tar.bz2
samba-f45abeae40495460e29347ebc3c73b9ffece847d.zip
tevent: maintain a list of disabled events in the poll backend
We need to avoid passing pollfd.events == 0, to poll(), as it will report POLLERR and POLLHUP events, but our caller does not expect the event handler to be called. Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
-rw-r--r--lib/tevent/tevent_poll.c55
1 files changed, 48 insertions, 7 deletions
diff --git a/lib/tevent/tevent_poll.c b/lib/tevent/tevent_poll.c
index 792abefd48..9e2cf1ee05 100644
--- a/lib/tevent/tevent_poll.c
+++ b/lib/tevent/tevent_poll.c
@@ -38,6 +38,13 @@ struct poll_event_context {
* picked up yet by poll_event_loop_once
*/
struct tevent_fd *fresh;
+ /*
+ * A DLIST for disabled fde's.
+ */
+ struct tevent_fd *disabled;
+ /*
+ * one or more events were deleted or disabled
+ */
bool deleted;
/*
@@ -66,6 +73,12 @@ static int poll_event_context_destructor(struct poll_event_context *poll_ev)
DLIST_REMOVE(poll_ev->fresh, fd);
}
+ for (fd = poll_ev->disabled; fd; fd = fn) {
+ fn = fd->next;
+ fd->event_ctx = NULL;
+ DLIST_REMOVE(poll_ev->disabled, fd);
+ }
+
if (poll_ev->signal_fd == -1) {
/*
* Non-threaded, no signal pipe
@@ -220,8 +233,10 @@ static int poll_event_fd_destructor(struct tevent_fd *fde)
ev->additional_data, struct poll_event_context);
if (del_idx == UINT64_MAX) {
+ struct tevent_fd **listp =
+ (struct tevent_fd **)fde->additional_data;
- DLIST_REMOVE(poll_ev->fresh, fde);
+ DLIST_REMOVE((*listp), fde);
goto done;
}
@@ -256,10 +271,18 @@ _PRIVATE_ void tevent_poll_event_add_fd_internal(struct tevent_context *ev,
{
struct poll_event_context *poll_ev = talloc_get_type_abort(
ev->additional_data, struct poll_event_context);
+ struct tevent_fd **listp;
+
+ if (fde->flags != 0) {
+ listp = &poll_ev->fresh;
+ } else {
+ listp = &poll_ev->disabled;
+ }
fde->additional_flags = UINT64_MAX;
- fde->additional_data = NULL;
- DLIST_ADD(poll_ev->fresh, fde);
+ fde->additional_data = listp;
+
+ DLIST_ADD((*listp), fde);
talloc_set_destructor(fde, poll_event_fd_destructor);
}
@@ -327,11 +350,28 @@ static void poll_event_set_fd_flags(struct tevent_fd *fde, uint16_t flags)
fde->flags = flags;
if (idx == UINT64_MAX) {
+ struct tevent_fd **listp =
+ (struct tevent_fd **)fde->additional_data;
+
+ /*
+ * We move it between the fresh and disabled lists.
+ */
+ DLIST_REMOVE((*listp), fde);
+ tevent_poll_event_add_fd_internal(ev, fde);
+ poll_event_wake_pollthread(poll_ev);
+ return;
+ }
+
+ if (fde->flags == 0) {
/*
- * poll_event_setup_fresh not yet called after this fde was
- * added. We don't have to do anything to transfer the changed
- * flags to the array passed to poll(2)
+ * We need to remove it from the array
+ * and move it to the disabled list.
*/
+ poll_ev->fdes[idx] = NULL;
+ poll_ev->deleted = true;
+ DLIST_REMOVE(ev->fd_events, fde);
+ tevent_poll_event_add_fd_internal(ev, fde);
+ poll_event_wake_pollthread(poll_ev);
return;
}
@@ -602,7 +642,8 @@ static int poll_event_loop_wait(struct tevent_context *ev,
ev->timer_events ||
ev->immediate_events ||
ev->signal_events ||
- poll_ev->fresh) {
+ poll_ev->fresh ||
+ poll_ev->disabled) {
int ret;
ret = _tevent_loop_once(ev, location);
if (ret != 0) {