From dc246a7f3e0f6e575b89b38ee84d50b072bd7a72 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 9 May 2007 21:57:51 +0200 Subject: [PATCH] [BUG] two missing states in sepoll transition matrix Two states were missing in the speculative epoll state transition matrix. This could cause some timeouts and unhandled events. The problem showed up in TCP mode with a fast server at high session rates, but could in theory also affect HTTP mode. --- src/ev_sepoll.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/ev_sepoll.c b/src/ev_sepoll.c index 74917add8..c3b777647 100644 --- a/src/ev_sepoll.c +++ b/src/ev_sepoll.c @@ -232,10 +232,16 @@ REGPRM1 static void __fd_clo(int fd) fd_list[fd].e &= ~(FD_EV_MASK); } +/* + * operations to perform when reaching _do_poll() for some FDs in the spec + * queue depending on their state. This is mainly used to cleanup some FDs + * which are in STOP state. It is also used to compute EPOLL* flags when + * switching from SPEC to WAIT. + */ static struct ev_to_epoll { char op; // epoll opcode to switch from spec to wait, 0 if none char m; // inverted mask for existing events - char ev; // remainint epoll events after change + char ev; // remaining epoll events after change char pad; } ev_to_epoll[16] = { [FD_EV_IDLE_W | FD_EV_STOP_R] = { .op=EPOLL_CTL_DEL, .m=FD_EV_MASK_R }, @@ -245,6 +251,8 @@ static struct ev_to_epoll { [FD_EV_WAIT_W | FD_EV_STOP_R] = { .op=EPOLL_CTL_MOD, .m=FD_EV_MASK_R, .ev=EPOLLOUT }, [FD_EV_STOP_W | FD_EV_WAIT_R] = { .op=EPOLL_CTL_MOD, .m=FD_EV_MASK_W, .ev=EPOLLIN }, [FD_EV_STOP_W | FD_EV_STOP_R] = { .op=EPOLL_CTL_DEL, .m=FD_EV_MASK_R|FD_EV_MASK_W }, + [FD_EV_SPEC_W | FD_EV_WAIT_R] = { .ev=EPOLLIN }, + [FD_EV_WAIT_W | FD_EV_SPEC_R] = { .ev=EPOLLOUT }, [FD_EV_WAIT_W | FD_EV_WAIT_R] = { .ev=EPOLLIN|EPOLLOUT }, }; @@ -274,10 +282,10 @@ REGPRM2 static void _do_poll(struct poller *p, int wait_time) opcode = ev_to_epoll[fd_list[fd].e].op; if (opcode) { - ev.events = ev_to_epoll[fd_list[fd].e].ev; ev.data.fd = fd; - epoll_ctl(epoll_fd, opcode, fd, &ev); + ev.events = ev_to_epoll[fd_list[fd].e].ev; fd_list[fd].e &= ~(unsigned int)ev_to_epoll[fd_list[fd].e].m; + epoll_ctl(epoll_fd, opcode, fd, &ev); } if (!(fd_list[fd].e & FD_EV_RW_SL)) {