1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-13 13:18:06 +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) static int aio_event_loop(struct aio_event_context *aio_ev, struct timeval *tvalp)
{ {
int ret, i; int ret, i;
uint32_t destruction_count = aio_ev->destruction_count; uint32_t destruction_count = ++aio_ev->destruction_count;
struct timespec timeout; struct timespec timeout;
struct io_event events[8]; 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; int ret, i;
#define MAXEVENTS 8 #define MAXEVENTS 8
struct epoll_event events[MAXEVENTS]; struct epoll_event events[MAXEVENTS];
uint32_t destruction_count = epoll_ev->destruction_count; uint32_t destruction_count = ++epoll_ev->destruction_count;
int timeout = -1; int timeout = -1;
if (epoll_ev->epoll_fd == -1) return -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 */ /* information for exiting from the event loop */
int exit_code; int exit_code;
/* this is changed by the destructors for the fd event /* this is incremented when the loop over events causes something which
type. It is used to detect event destruction by event could change the events yet to be processed */
handlers, which means the code that is calling the event
handler needs to assume that the linked list is no longer
valid
*/
uint32_t destruction_count; 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; fd_set r_fds, w_fds;
struct fd_event *fde; struct fd_event *fde;
int selrtn; 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 */ /* we maybe need to recalculate the maxfd */
if (select_ev->maxfd == EVENT_INVALID_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; int ret, i;
#define MAXEVENTS 8 #define MAXEVENTS 8
struct epoll_event events[MAXEVENTS]; struct epoll_event events[MAXEVENTS];
uint32_t destruction_count = std_ev->destruction_count; uint32_t destruction_count = ++std_ev->destruction_count;
int timeout = -1; int timeout = -1;
if (std_ev->epoll_fd == -1) return -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; fd_set r_fds, w_fds;
struct fd_event *fde; struct fd_event *fde;
int selrtn; 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 */ /* we maybe need to recalculate the maxfd */
if (std_ev->maxfd == EVENT_INVALID_MAXFD) { if (std_ev->maxfd == EVENT_INVALID_MAXFD) {