diff options
author | Andrew Tridgell <tridge@samba.org> | 2007-02-06 04:43:48 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 14:44:41 -0500 |
commit | b9f10ebb99a76820085af514b102ff75a5694c57 (patch) | |
tree | 50d771fa7cd70c41cf133f6570700d036b41fcc6 /source4/lib/events | |
parent | 96325d3f763a470272c3b4373afa96f6d54f37b9 (diff) | |
download | samba-b9f10ebb99a76820085af514b102ff75a5694c57.tar.gz samba-b9f10ebb99a76820085af514b102ff75a5694c57.tar.bz2 samba-b9f10ebb99a76820085af514b102ff75a5694c57.zip |
r21171: fixed a bug related to recursive event handling.
If this happens:
- two sockets are readable, and select/epoll/aio returns both of
them
- read event on socket1 is called
- inside that read event an event_loop_once is called, this returns that
socket2 is readable
- read event on socket2 is called
- event_loop_once returns
- top level event handler then calls read event on socket2 (as it
still has that listed as readable)
- read handler for socket2 returns zero byte read, which is
interpreted as end of file
- socket is incorrectly closed
this happened with ctdb, but it could happen anywhere (just
rarely). The fix is trivial - ensure we break out of the event loop
when we have been called recursively.
(This used to be commit e042002bb5ee8974220e1ade56b64389571f75a6)
Diffstat (limited to 'source4/lib/events')
-rw-r--r-- | source4/lib/events/events_aio.c | 2 | ||||
-rw-r--r-- | source4/lib/events/events_epoll.c | 2 | ||||
-rw-r--r-- | source4/lib/events/events_select.c | 10 | ||||
-rw-r--r-- | source4/lib/events/events_standard.c | 4 |
4 files changed, 7 insertions, 11 deletions
diff --git a/source4/lib/events/events_aio.c b/source4/lib/events/events_aio.c index cd3c32a9b8..90d4bdcc1f 100644 --- a/source4/lib/events/events_aio.c +++ b/source4/lib/events/events_aio.c @@ -219,7 +219,7 @@ static int setup_epoll_wait(struct aio_event_context *aio_ev) static int aio_event_loop(struct aio_event_context *aio_ev, struct timeval *tvalp) { int ret, i; - uint32_t destruction_count = aio_ev->destruction_count; + uint32_t destruction_count = ++aio_ev->destruction_count; struct timespec timeout; struct io_event events[8]; diff --git a/source4/lib/events/events_epoll.c b/source4/lib/events/events_epoll.c index efcbb97f0b..58eeb08cd5 100644 --- a/source4/lib/events/events_epoll.c +++ b/source4/lib/events/events_epoll.c @@ -204,7 +204,7 @@ static int epoll_event_loop(struct epoll_event_context *epoll_ev, struct timeval int ret, i; #define MAXEVENTS 8 struct epoll_event events[MAXEVENTS]; - uint32_t destruction_count = epoll_ev->destruction_count; + uint32_t destruction_count = ++epoll_ev->destruction_count; int timeout = -1; if (epoll_ev->epoll_fd == -1) return -1; diff --git a/source4/lib/events/events_select.c b/source4/lib/events/events_select.c index ea84353183..36b5afc42e 100644 --- a/source4/lib/events/events_select.c +++ b/source4/lib/events/events_select.c @@ -47,12 +47,8 @@ struct select_event_context { /* information for exiting from the event loop */ int exit_code; - /* this is changed by the destructors for the fd event - type. It is used to detect event destruction by event - handlers, which means the code that is calling the event - handler needs to assume that the linked list is no longer - valid - */ + /* this is incremented when the loop over events causes something which + could change the events yet to be processed */ uint32_t destruction_count; }; @@ -177,7 +173,7 @@ static int select_event_loop_select(struct select_event_context *select_ev, stru fd_set r_fds, w_fds; struct fd_event *fde; int selrtn; - uint32_t destruction_count = select_ev->destruction_count; + uint32_t destruction_count = ++select_ev->destruction_count; /* we maybe need to recalculate the maxfd */ if (select_ev->maxfd == EVENT_INVALID_MAXFD) { diff --git a/source4/lib/events/events_standard.c b/source4/lib/events/events_standard.c index 9c470235d0..48959526c0 100644 --- a/source4/lib/events/events_standard.c +++ b/source4/lib/events/events_standard.c @@ -219,7 +219,7 @@ static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tv int ret, i; #define MAXEVENTS 8 struct epoll_event events[MAXEVENTS]; - uint32_t destruction_count = std_ev->destruction_count; + uint32_t destruction_count = ++std_ev->destruction_count; int timeout = -1; if (std_ev->epoll_fd == -1) return -1; @@ -425,7 +425,7 @@ static int std_event_loop_select(struct std_event_context *std_ev, struct timeva fd_set r_fds, w_fds; struct fd_event *fde; int selrtn; - uint32_t destruction_count = std_ev->destruction_count; + uint32_t destruction_count = ++std_ev->destruction_count; /* we maybe need to recalculate the maxfd */ if (std_ev->maxfd == EVENT_INVALID_MAXFD) { |