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); }