From: Willy Tarreau Date: Sun, 14 Dec 2008 08:04:47 +0000 (+0100) Subject: [MEDIUM] indicate when we don't care about read timeout X-Git-Tag: v1.3.16-rc1~88 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=86491c3164b50978fb6ee347920aa440b7ac8050;p=thirdparty%2Fhaproxy.git [MEDIUM] indicate when we don't care about read timeout Sometimes we don't care about a read timeout, for instance, from the client when waiting for the server, but we still want the client to be able to read. Till now it was done by articially forcing the read timeout to ETERNITY. But this will cause trouble when we want the low level stream sock to communicate without waking the session up. So we add a BF_READ_NOEXP flag to indicate that when the read timeout is to be set, it might have to be set to ETERNITY. Since BF_READ_ENA was not used, we replaced this flag. --- diff --git a/include/proto/buffers.h b/include/proto/buffers.h index be1c9492a2..64427963d2 100644 --- a/include/proto/buffers.h +++ b/include/proto/buffers.h @@ -73,7 +73,7 @@ static inline int buffer_isfull(const struct buffer *buf) { */ static inline void buffer_check_timeouts(struct buffer *b) { - if (likely(!(b->flags & (BF_SHUTR|BF_READ_TIMEOUT|BF_READ_ACTIVITY))) && + if (likely(!(b->flags & (BF_SHUTR|BF_READ_TIMEOUT|BF_READ_ACTIVITY|BF_READ_NOEXP))) && unlikely(tick_is_expired(b->rex, now_ms))) b->flags |= BF_READ_TIMEOUT; diff --git a/include/types/buffers.h b/include/types/buffers.h index 27d32713da..d8f71188b4 100644 --- a/include/types/buffers.h +++ b/include/types/buffers.h @@ -59,7 +59,7 @@ #define BF_FULL 0x000010 /* buffer cannot accept any more data (l >= rlim-data) */ #define BF_SHUTR 0x000020 /* producer has already shut down */ #define BF_SHUTR_NOW 0x000040 /* the producer must shut down for reads immediately */ -#define BF_READ_ENA 0x000080 /* producer is allowed to feed data into the buffer */ +#define BF_READ_NOEXP 0x000080 /* producer should not expire */ #define BF_WRITE_NULL 0x000100 /* write(0) or connect() succeeded on consumer side */ #define BF_WRITE_PARTIAL 0x000200 /* some data were written to the consumer */ @@ -93,7 +93,7 @@ #define BF_MASK_ANALYSER (BF_READ_ATTACHED|BF_READ_ACTIVITY|BF_READ_TIMEOUT|BF_ANA_TIMEOUT|BF_WRITE_ACTIVITY) /* Mask for static flags which are not events, but might change during processing */ -#define BF_MASK_STATIC (BF_EMPTY|BF_FULL|BF_HIJACK|BF_WRITE_ENA|BF_READ_ENA|BF_SHUTR|BF_SHUTW|BF_SHUTR_NOW|BF_SHUTW_NOW) +#define BF_MASK_STATIC (BF_EMPTY|BF_FULL|BF_HIJACK|BF_WRITE_ENA|BF_SHUTR|BF_SHUTW|BF_SHUTR_NOW|BF_SHUTW_NOW) /* Analysers (buffer->analysers). diff --git a/src/proto_uxst.c b/src/proto_uxst.c index 21c50fc573..806e09e93a 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -717,6 +717,8 @@ void uxst_process_session(struct task *t, int *next) buffer_check_timeouts(s->rep); } + s->req->flags &= ~BF_READ_NOEXP; + /* copy req/rep flags so that we can detect shutdowns */ rqf_last = s->req->flags; rpf_last = s->rep->flags; @@ -934,8 +936,10 @@ void uxst_process_session(struct task *t, int *next) */ if ((s->rep->flags & (BF_WRITE_ENA|BF_SHUTR)) == 0 && - (tick_isset(s->req->wex) || tick_isset(s->rep->rex))) + (tick_isset(s->req->wex) || tick_isset(s->rep->rex))) { + s->req->flags |= BF_READ_NOEXP; s->req->rex = TICK_ETERNITY; + } t->expire = tick_first(tick_first(s->req->rex, s->req->wex), tick_first(s->rep->rex, s->rep->wex)); diff --git a/src/session.c b/src/session.c index 95ece53fa6..e163fdfb2f 100644 --- a/src/session.c +++ b/src/session.c @@ -556,6 +556,8 @@ void process_session(struct task *t, int *next) buffer_check_timeouts(s->rep); } + s->req->flags &= ~BF_READ_NOEXP; + /* copy req/rep flags so that we can detect shutdowns */ rqf_last = s->req->flags; rpf_last = s->rep->flags; @@ -954,8 +956,10 @@ resync_stream_interface: */ if ((s->rep->flags & (BF_WRITE_ENA|BF_SHUTR)) == 0 && - (tick_isset(s->req->wex) || tick_isset(s->rep->rex))) + (tick_isset(s->req->wex) || tick_isset(s->rep->rex))) { + s->req->flags |= BF_READ_NOEXP; s->req->rex = TICK_ETERNITY; + } t->expire = tick_first(tick_first(s->req->rex, s->req->wex), tick_first(s->rep->rex, s->rep->wex)); diff --git a/src/stream_sock.c b/src/stream_sock.c index 68471ed174..f043072847 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -431,13 +431,12 @@ int stream_sock_write(int fd) { if (tick_isset(b->wex) && b->flags & BF_WRITE_PARTIAL) { b->wex = tick_add_ifset(now_ms, b->wto); - if (tick_isset(b->wex)) { + if (tick_isset(b->wex) & tick_isset(si->ib->rex)) { /* FIXME: to prevent the client from expiring read timeouts during writes, * we refresh it. A solution would be to merge read+write timeouts into a * unique one, although that needs some study particularly on full-duplex * TCP connections. */ - if (tick_isset(b->rex) && !(b->flags & BF_SHUTR)) - b->rex = b->wex; + si->ib->rex = b->wex; } } @@ -561,7 +560,8 @@ void stream_sock_data_finish(struct stream_interface *si) * update it if is was not yet set, or if we already got some read status. */ EV_FD_COND_S(fd, DIR_RD); - if (!tick_isset(ib->rex) || ib->flags & BF_READ_ACTIVITY) + if (!(ib->flags & BF_READ_NOEXP) && + (!tick_isset(ib->rex) || ib->flags & BF_READ_ACTIVITY)) ib->rex = tick_add_ifset(now_ms, ib->rto); } }