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:
parent
a4a394c9bb
commit
e042002bb5
@ -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];
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user