1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-25 23:21:54 +03:00

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 commit is contained in:
Andrew Tridgell 2007-02-06 04:43:48 +00:00 committed by Gerald (Jerry) Carter
parent a4a394c9bb
commit e042002bb5
4 changed files with 7 additions and 11 deletions

View File

@ -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];

View File

@ -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;

View File

@ -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) {

View File

@ -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) {