From d5b341d873bc326843d80dd15d3cd3ef465234ae Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 17 Feb 2013 23:21:28 +0100 Subject: [PATCH] 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 Reviewed-by: Jeremy Allison --- 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 81a7176f8ee..68885e94c0f 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; } -- 2.11.4.GIT