]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] process_srv_data: ensure that we always correctly re-arm timeouts
authorWilly Tarreau <w@1wt.eu>
Wed, 27 Aug 2008 19:10:25 +0000 (21:10 +0200)
committerWilly Tarreau <w@1wt.eu>
Sun, 2 Nov 2008 09:19:05 +0000 (10:19 +0100)
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.

src/proto_http.c

index 2eb7baac1bf859fe8292bfc2ced13d01f580b10b..b53bb6c8185829a065e532f4bf58d0b2076b5c96 100644 (file)
@@ -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,