From b1ff9dbde2476caa3d5029a1bd14fd372225e3c2 Mon Sep 17 00:00:00 2001 From: willy tarreau Date: Sat, 17 Dec 2005 13:51:03 +0100 Subject: [PATCH] * released 1.1.20 * fixed two problems with time-outs, one where a server would be logged as timed out during transfer that take longer to complete than the fixed time-out, and one where clients were logged as timed-out during the data phase because they didn't have anything to send. This sometimes caused slow client connections to close too early while in fact there was no problem. The proper fix would be to have a per-fd time-out with conditions depending on the state of the HTTP FSM. --- CHANGELOG | 9 +++++++ haproxy.c | 71 ++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 63 insertions(+), 17 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index bbd4d6b27..47512a73c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,15 @@ ChangeLog : =========== +2003/04/21 : 1.1.20 + - fixed two problems with time-outs, one where a server would be logged as + timed out during transfer that take longer to complete than the fixed + time-out, and one where clients were logged as timed-out during the data + phase because they didn't have anything to send. This sometimes caused + slow client connections to close too early while in fact there was no + problem. The proper fix would be to have a per-fd time-out with + conditions depending on the state of the HTTP FSM. + 2003/04/16 : 1.1.19 - haproxy was NOT RFC compliant because it was case-sensitive on HTTP "Cookie:" and "Set-Cookie:" headers. This caused JVM 1.4 to fail on diff --git a/haproxy.c b/haproxy.c index 7050fefbe..5c3572641 100644 --- a/haproxy.c +++ b/haproxy.c @@ -53,8 +53,8 @@ #include #endif -#define HAPROXY_VERSION "1.1.19" -#define HAPROXY_DATE "2003/04/16" +#define HAPROXY_VERSION "1.1.20" +#define HAPROXY_DATE "2003/04/21" /* this is for libc5 for example */ #ifndef TCP_NODELAY @@ -1524,7 +1524,7 @@ int event_cli_read(int fd) { } if (s->res_cr != RES_SILENT) { - if (s->proxy->clitimeout) + if (s->proxy->clitimeout && FD_ISSET(fd, StaticReadEvent)) tv_delayfrom(&s->crexpire, &now, s->proxy->clitimeout); else tv_eternity(&s->crexpire); @@ -1619,7 +1619,7 @@ int event_srv_read(int fd) { } if (s->res_sr != RES_SILENT) { - if (s->proxy->srvtimeout) + if (s->proxy->srvtimeout && FD_ISSET(fd, StaticReadEvent)) tv_delayfrom(&s->srexpire, &now, s->proxy->srvtimeout); else tv_eternity(&s->srexpire); @@ -1661,6 +1661,8 @@ int event_cli_write(int fd) { if (max == 0) { s->res_cw = RES_NULL; task_wakeup(&rq, t); + tv_eternity(&s->cwexpire); + FD_CLR(fd, StaticWriteEvent); return 0; } @@ -1702,8 +1704,11 @@ int event_cli_write(int fd) { fdtab[fd].state = FD_STERROR; } - if (s->proxy->clitimeout) + if (s->proxy->clitimeout) { tv_delayfrom(&s->cwexpire, &now, s->proxy->clitimeout); + /* FIXME: to avoid the client to read-time-out during writes, we refresh it */ + s->crexpire = s->cwexpire; + } else tv_eternity(&s->cwexpire); @@ -1744,6 +1749,8 @@ int event_srv_write(int fd) { s->res_sw = RES_NULL; task_wakeup(&rq, t); fdtab[fd].state = FD_STREADY; + tv_eternity(&s->swexpire); + FD_CLR(fd, StaticWriteEvent); return 0; } @@ -1786,8 +1793,11 @@ int event_srv_write(int fd) { fdtab[fd].state = FD_STERROR; } - if (s->proxy->srvtimeout) + if (s->proxy->srvtimeout) { tv_delayfrom(&s->swexpire, &now, s->proxy->srvtimeout); + /* FIXME: to avoid the server to read-time-out during writes, we refresh it */ + s->srexpire = s->swexpire; + } else tv_eternity(&s->swexpire); @@ -2025,7 +2035,7 @@ int event_accept(int fd) { s->req->total = 0; s->req->h = s->req->r = s->req->lr = s->req->w = s->req->data; /* r and w will be reset further */ s->req->rlim = s->req->data + BUFSIZE; - if (s->cli_state == CL_STHEADERS) /* reserver some space for header rewriting */ + if (s->cli_state == CL_STHEADERS) /* reserve some space for header rewriting */ s->req->rlim -= MAXREWRITE; if ((s->rep = pool_alloc(buffer)) == NULL) { /* no memory */ @@ -2706,7 +2716,7 @@ int process_cli(struct session *t) { shutdown(t->cli_fd, SHUT_WR); t->cli_state = CL_STSHUTW; if (!(t->flags & SN_ERR_MASK)) - t->flags |= SN_ERR_CLICL; + t->flags |= SN_ERR_CLITO; if (!(t->flags & SN_FINST_MASK)) t->flags |= SN_FINST_D; return 1; @@ -2741,8 +2751,11 @@ int process_cli(struct session *t) { else { /* buffer not empty */ if (! FD_ISSET(t->cli_fd, StaticWriteEvent)) { FD_SET(t->cli_fd, StaticWriteEvent); /* restart writing */ - if (t->proxy->clitimeout) + if (t->proxy->clitimeout) { tv_delayfrom(&t->cwexpire, &now, t->proxy->clitimeout); + /* FIXME: to avoid the client to read-time-out during writes, we refresh it */ + t->crexpire = t->cwexpire; + } else tv_eternity(&t->cwexpire); } @@ -2786,8 +2799,11 @@ int process_cli(struct session *t) { else { /* buffer not empty */ if (! FD_ISSET(t->cli_fd, StaticWriteEvent)) { FD_SET(t->cli_fd, StaticWriteEvent); /* restart writing */ - if (t->proxy->clitimeout) + if (t->proxy->clitimeout) { tv_delayfrom(&t->cwexpire, &now, t->proxy->clitimeout); + /* FIXME: to avoid the client to read-time-out during writes, we refresh it */ + t->crexpire = t->cwexpire; + } else tv_eternity(&t->cwexpire); } @@ -2961,10 +2977,19 @@ int process_srv(struct session *t) { t->logs.t_connect = tv_diff(&t->logs.tv_accept, &now); //fprintf(stderr,"3: c=%d, s=%d\n", c, s); - if (req->l == 0) /* nothing to write */ + if (req->l == 0) /* nothing to write */ { FD_CLR(t->srv_fd, StaticWriteEvent); - else /* need the right to write */ + tv_eternity(&t->swexpire); + } else /* need the right to write */ { FD_SET(t->srv_fd, StaticWriteEvent); + if (t->proxy->srvtimeout) { + tv_delayfrom(&t->swexpire, &now, t->proxy->srvtimeout); + /* FIXME: to avoid the server to read-time-out during writes, we refresh it */ + t->srexpire = t->swexpire; + } + else + tv_eternity(&t->swexpire); + } if (t->proxy->mode == PR_MODE_TCP) { /* let's allow immediate data connection in this case */ FD_SET(t->srv_fd, StaticReadEvent); @@ -3314,8 +3339,11 @@ int process_srv(struct session *t) { else { /* client buffer not empty */ if (! FD_ISSET(t->srv_fd, StaticWriteEvent)) { FD_SET(t->srv_fd, StaticWriteEvent); /* restart writing */ - if (t->proxy->srvtimeout) + if (t->proxy->srvtimeout) { tv_delayfrom(&t->swexpire, &now, t->proxy->srvtimeout); + /* FIXME: to avoid the server to read-time-out during writes, we refresh it */ + t->srexpire = t->swexpire; + } else tv_eternity(&t->swexpire); } @@ -3374,22 +3402,28 @@ int process_srv(struct session *t) { t->flags |= SN_FINST_D; return 1; } - else if (req->l == 0) { + + /* recompute request time-outs */ + if (req->l == 0) { if (FD_ISSET(t->srv_fd, StaticWriteEvent)) { FD_CLR(t->srv_fd, StaticWriteEvent); /* stop writing */ tv_eternity(&t->swexpire); } } - else { /* buffer not empty */ + else { /* buffer not empty, there are still data to be transferred */ if (! FD_ISSET(t->srv_fd, StaticWriteEvent)) { FD_SET(t->srv_fd, StaticWriteEvent); /* restart writing */ - if (t->proxy->srvtimeout) + if (t->proxy->srvtimeout) { tv_delayfrom(&t->swexpire, &now, t->proxy->srvtimeout); + /* FIXME: to avoid the server to read-time-out during writes, we refresh it */ + t->srexpire = t->swexpire; + } else tv_eternity(&t->swexpire); } } + /* recompute response time-outs */ if (rep->l == BUFSIZE) { /* no room to read more data */ if (FD_ISSET(t->srv_fd, StaticReadEvent)) { FD_CLR(t->srv_fd, StaticReadEvent); @@ -3450,8 +3484,11 @@ int process_srv(struct session *t) { else { /* buffer not empty */ if (! FD_ISSET(t->srv_fd, StaticWriteEvent)) { FD_SET(t->srv_fd, StaticWriteEvent); /* restart writing */ - if (t->proxy->srvtimeout) + if (t->proxy->srvtimeout) { tv_delayfrom(&t->swexpire, &now, t->proxy->srvtimeout); + /* FIXME: to avoid the server to read-time-out during writes, we refresh it */ + t->srexpire = t->swexpire; + } else tv_eternity(&t->swexpire); }