From: Willy Tarreau Date: Wed, 27 Aug 2008 19:10:25 +0000 (+0200) Subject: [MEDIUM] process_srv_data: ensure that we always correctly re-arm timeouts X-Git-Tag: v1.3.16-rc1~172 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8a8188301b710b244a57d5e0aff00e1e5ee27882;p=thirdparty%2Fhaproxy.git [MEDIUM] process_srv_data: ensure that we always correctly re-arm timeouts We really want to ensure that we don't miss a timeout update and do not update them for nothing. So the code takes care of updating the timeout in the two following circumstances : - it was not set - some I/O has been performed Maybe we'll be able to remove that from stream_sock_{read|write}, or we'll find a way to ensure that we never have to re-enable this. --- diff --git a/src/proto_http.c b/src/proto_http.c index 2eb7baac1b..b53bb6c818 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -3924,12 +3924,18 @@ int process_srv_data(struct session *t) } /* Read not closed, update FD status and timeout for reads */ else if (rep->flags & (BF_FULL|BF_HIJACK)) { - if (EV_FD_COND_C(fd, DIR_RD)) - rep->rex = TICK_ETERNITY; + /* stop reading */ + EV_FD_COND_C(fd, DIR_RD); + rep->rex = TICK_ETERNITY; } else { + /* (re)start reading and update timeout. Note: we don't recompute the timeout + * everytime we get here, otherwise it would risk never to expire. We only + * update it if is was not yet set, or if we already got some read status. + */ EV_FD_COND_S(fd, DIR_RD); - rep->rex = tick_add_ifset(now_ms, rep->rto); + if (!tick_isset(rep->rex) || rep->flags & BF_READ_STATUS) + rep->rex = tick_add_ifset(now_ms, rep->rto); } } @@ -3960,16 +3966,18 @@ int process_srv_data(struct session *t) /* Write not closed, update FD status and timeout for writes */ else if ((req->flags & (BF_EMPTY|BF_MAY_FORWARD)) != BF_MAY_FORWARD) { /* stop writing */ - if (EV_FD_COND_C(fd, DIR_WR)) - req->wex = TICK_ETERNITY; + EV_FD_COND_C(fd, DIR_WR); + req->wex = TICK_ETERNITY; } else { - /* buffer not empty, there are still data to be transferred */ + /* (re)start writing and update timeout. Note: we don't recompute the timeout + * everytime we get here, otherwise it would risk never to expire. We only + * update it if is was not yet set, or if we already got some write status. + */ EV_FD_COND_S(fd, DIR_WR); - if (!tick_isset(req->wex)) { - /* restart writing */ + if (!tick_isset(req->wex) || req->flags & BF_WRITE_STATUS) { req->wex = tick_add_ifset(now_ms, req->wto); - if (!(rep->flags & BF_SHUTR) && tick_isset(req->wex) && tick_isset(rep->rex)) { + if (tick_isset(req->wex) && !(rep->flags & BF_SHUTR) && tick_isset(rep->rex)) { /* Note: depending on the protocol, we don't know if we're waiting * for incoming data or not. So in order to prevent the socket from * expiring read timeouts during writes, we refresh the read timeout,