diff options
author | Stefan Metzmacher <metze@samba.org> | 2013-02-28 17:07:28 +0100 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2013-03-01 11:59:42 -0800 |
commit | f45abeae40495460e29347ebc3c73b9ffece847d (patch) | |
tree | 7ace1cb67180959eb3d08c74152c7b23e7db2aa7 | |
parent | ef8130fdbf50384dca3669ab27de4863490d5cb1 (diff) | |
download | samba-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.c | 55 |
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) { |