* 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.
diff --git a/CHANGELOG b/CHANGELOG
index bbd4d6b..47512a7 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 7050fef..5c35726 100644
--- a/haproxy.c
+++ b/haproxy.c
@@ -53,8 +53,8 @@
#include <linux/netfilter_ipv4.h>
#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 @@
}
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
}