summaryrefslogtreecommitdiff
path: root/lib/tevent
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2013-02-21 14:41:24 +0100
committerJeremy Allison <jra@samba.org>2013-03-01 11:59:28 -0800
commit8e3ef659f876573bd7abb7d0e707369157232125 (patch)
treed8d3365bc4d4b38f44bef402b8ac15b2c3ed71d9 /lib/tevent
parentd5b341d873bc326843d80dd15d3cd3ef465234ae (diff)
downloadsamba-8e3ef659f876573bd7abb7d0e707369157232125.tar.gz
samba-8e3ef659f876573bd7abb7d0e707369157232125.tar.bz2
samba-8e3ef659f876573bd7abb7d0e707369157232125.zip
tevent: make sure we cleanup the array passed to poll() after deleting an event
If we don't cleanup the array passed to poll after an event was deleted, we may pass a bad file descriptor to poll(). This was found by the following test failure in Samba's autobuild, while removing the epoll support from the "standard" backend. [48/1555 in 4m37s] samba3.smbtorture_s3.plain(s3dc).LOCK4 UNEXPECTED(failure): samba3.smbtorture_s3.plain(s3dc).LOCK4.smbtorture(s3dc) REASON: _StringException: _StringException: using seed 1361530718 host=127.0.0.2 share=tmp user=metze myname=sn-devel-104 Running LOCK4 starting locktest4 Failed to create file: NT_STATUS_INVALID_HANDLE finished locktest4 TEST LOCK4 FAILED! LOCK4 took 190.492 secs Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'lib/tevent')
-rw-r--r--lib/tevent/tevent_poll.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/lib/tevent/tevent_poll.c b/lib/tevent/tevent_poll.c
index 68885e94c0..0928cbd6cb 100644
--- a/lib/tevent/tevent_poll.c
+++ b/lib/tevent/tevent_poll.c
@@ -38,6 +38,7 @@ struct poll_event_context {
* picked up yet by poll_event_loop_once
*/
struct tevent_fd *fresh;
+ bool deleted;
/*
* These two arrays are maintained together.
@@ -219,6 +220,7 @@ static int poll_event_fd_destructor(struct tevent_fd *fde)
ev->additional_data, struct poll_event_context);
poll_ev->fdes[del_idx] = NULL;
+ poll_ev->deleted = true;
poll_event_wake_pollthread(poll_ev);
done:
return tevent_common_fd_destructor(fde);
@@ -363,6 +365,34 @@ static bool poll_event_setup_fresh(struct tevent_context *ev,
struct tevent_fd *fde, *next;
unsigned num_fresh, num_fds;
+ if (poll_ev->deleted) {
+ unsigned first_fd = (poll_ev->signal_fd != -1) ? 1 : 0;
+ unsigned i;
+
+ for (i=first_fd; i < poll_ev->num_fds;) {
+ fde = poll_ev->fdes[i];
+ if (fde != NULL) {
+ i++;
+ continue;
+ }
+
+ /*
+ * This fde was talloc_free()'ed. Delete it
+ * 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;
+ }
+ }
+ }
+ poll_ev->deleted = false;
+
if (poll_ev->fresh == NULL) {
return true;
}