From 08dedbe8981541ebbd043c51486a05d80f8e855f Mon Sep 17 00:00:00 2001 From: willy tarreau Date: Sun, 18 Dec 2005 01:13:48 +0100 Subject: [PATCH] * released 1.2.5.1 * dirty hack to fix a bug introduced with epoll : if we close an FD and immediately reassign it to another session through a connect(), the Prev{Read,Write}Events are not updated, which causes trouble detecting changes, thus leading to many timeouts at high loads. --- CHANGELOG | 6 ++++++ haproxy.c | 37 ++++++++++++++++++------------------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7db21e51e..d51cb3eb6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,12 @@ ChangeLog : =========== +2005/05/02 : 1.2.5.1 + - dirty hack to fix a bug introduced with epoll : if we close an FD and + immediately reassign it to another session through a connect(), the + Prev{Read,Write}Events are not updated, which causes trouble detecting + changes, thus leading to many timeouts at high loads. + 2005/04/30 : 1.2.5 (1.1.31) - changed the runtime argument to disable epoll() to '-de' - changed the runtime argument to disable poll() to '-dp' diff --git a/haproxy.c b/haproxy.c index 301ad25e9..ec726880b 100644 --- a/haproxy.c +++ b/haproxy.c @@ -653,6 +653,16 @@ static int stopping = 0; /* non zero means stopping in progress */ static struct timeval now = {0,0}; /* the current date at any moment */ static struct proxy defproxy; /* fake proxy used to assign default values on all instances */ +#if defined(ENABLE_EPOLL) +/* FIXME: this is dirty, but at the moment, there's no other solution to remove + * the old FDs from outside the loop. Perhaps we should export a global 'poll' + * structure with pointers to functions such as init_fd() and close_fd(), plus + * a private structure with several pointers to places such as below. + */ + +static fd_set *PrevReadEvent = NULL, *PrevWriteEvent = NULL; +#endif + static regmatch_t pmatch[MAX_MATCH]; /* rm_so, rm_eo for regular expressions */ /* this is used to drain data, and as a temporary buffer for sprintf()... */ static char trash[BUFSIZE]; @@ -1413,6 +1423,13 @@ static inline struct timeval *tv_min(struct timeval *tvmin, static inline void fd_delete(int fd) { FD_CLR(fd, StaticReadEvent); FD_CLR(fd, StaticWriteEvent); +#if defined(ENABLE_EPOLL) + if (PrevReadEvent) { + FD_CLR(fd, PrevReadEvent); + FD_CLR(fd, PrevWriteEvent); + } +#endif + close(fd); fdtab[fd].state = FD_STCLOSE; @@ -4695,8 +4712,7 @@ int process_chk(struct task *t) { } } } - //fprintf(stderr, "process_chk: 5\n"); - close(fd); + close(fd); /* socket creation error */ } if (!s->result) { /* nothing done */ @@ -4870,8 +4886,6 @@ int epoll_loop(int action) { struct epoll_event ev; /* private data */ - static int last_maxfd = 0; - static fd_set *PrevReadEvent = NULL, *PrevWriteEvent = NULL; static struct epoll_event *epoll_events = NULL; static int epoll_fd; @@ -4894,7 +4908,6 @@ int epoll_loop(int action) { if (PrevReadEvent) free(PrevReadEvent); if (epoll_events) free(epoll_events); close(epoll_fd); - last_maxfd = 0; epoll_fd = 0; return 1; } @@ -4918,20 +4931,6 @@ int epoll_loop(int action) { } #endif - - /* - * We'll first check if some fds have been closed recently, in which case - * we'll have to remove them from the previous epoll set. It's - * unnecessary to call epoll_ctl(DEL) because close() automatically - * removes the fds from the epoll set. - */ - for (fd = maxfd; fd < last_maxfd; fd++) { - ev.data.fd = fd; - FD_CLR(fd, PrevReadEvent); - FD_CLR(fd, PrevWriteEvent); - } - last_maxfd = maxfd; - for (fds = 0; (fds << INTBITS) < maxfd; fds++) { rn = ((int*)StaticReadEvent)[fds]; ro = ((int*)PrevReadEvent)[fds];