From 3c6ab2e28d8611aa66f9bd35d865e1e9cec49eb5 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 4 Sep 2008 11:19:41 +0200 Subject: [PATCH] [MEDIUM] use buffer_check_timeouts instead of stream_sock_check_timeouts() It's more appropriate to use buffer_check_timeouts() to check for buffer timeouts and si->shutw/shutr to shutdown the stream interfaces. --- include/proto/stream_sock.h | 1 + include/types/stream_interface.h | 1 + src/client.c | 2 ++ src/proto_http.c | 30 ++++++++++++++++++++++-------- src/stream_sock.c | 30 +++++++++++++++++++++++++++--- 5 files changed, 53 insertions(+), 11 deletions(-) diff --git a/include/proto/stream_sock.h b/include/proto/stream_sock.h index 45064bea9..d005be56f 100644 --- a/include/proto/stream_sock.h +++ b/include/proto/stream_sock.h @@ -36,6 +36,7 @@ int stream_sock_write(int fd); int stream_sock_data_check_timeouts(int fd); int stream_sock_data_update(int fd); int stream_sock_data_finish(int fd); +int stream_sock_shutr(struct stream_interface *si); int stream_sock_shutw(struct stream_interface *si); diff --git a/include/types/stream_interface.h b/include/types/stream_interface.h index cd7fb706a..ba8d7a76e 100644 --- a/include/types/stream_interface.h +++ b/include/types/stream_interface.h @@ -62,6 +62,7 @@ struct stream_interface { void *owner; /* generally a (struct task*) */ int fd; /* file descriptor for a stream driver when known */ unsigned int exp; /* wake up time for connect, queue, turn-around, ... */ + int (*shutr)(struct stream_interface *); /* shutr function */ int (*shutw)(struct stream_interface *); /* shutw function */ struct buffer *ib, *ob; /* input and output buffers */ unsigned int err_type; /* first error detected, one of SI_ET_* */ diff --git a/src/client.c b/src/client.c index 32e90ba4e..547e215da 100644 --- a/src/client.c +++ b/src/client.c @@ -174,6 +174,7 @@ int event_accept(int fd) { s->si[0].err_type = SI_ET_NONE; s->si[0].err_loc = NULL; s->si[0].owner = t; + s->si[0].shutr = stream_sock_shutr; s->si[0].shutw = stream_sock_shutw; s->si[0].fd = cfd; s->si[0].exp = TICK_ETERNITY; @@ -183,6 +184,7 @@ int event_accept(int fd) { s->si[1].err_type = SI_ET_NONE; s->si[1].err_loc = NULL; s->si[1].owner = t; + s->si[1].shutr = stream_sock_shutr; s->si[1].shutw = stream_sock_shutw; s->si[1].exp = TICK_ETERNITY; s->si[1].fd = -1; /* just to help with debugging */ diff --git a/src/proto_http.c b/src/proto_http.c index 0a09b2d1e..d5760aedd 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -661,15 +661,29 @@ void process_session(struct task *t, int *next) /* Check timeouts only during data phase for now */ if (unlikely(t->state & TASK_WOKEN_TIMER)) { - if (s->rep->cons->state == SI_ST_EST) { - stream_sock_data_check_timeouts(s->rep->cons->fd); - if (tick_is_expired(s->rep->analyse_exp, now_ms)) - s->rep->flags |= BF_ANA_TIMEOUT; + buffer_check_timeouts(s->req); + buffer_check_timeouts(s->rep); + + if (unlikely(s->req->flags & (BF_READ_TIMEOUT|BF_WRITE_TIMEOUT))) { + if (s->req->flags & BF_READ_TIMEOUT) { + buffer_shutw(s->req); + s->req->cons->shutr(s->req->prod); + } + if (s->req->flags & BF_WRITE_TIMEOUT) { + buffer_shutw(s->req); + s->req->cons->shutw(s->req->cons); + } } - if (s->req->cons->state == SI_ST_EST) { - stream_sock_data_check_timeouts(s->req->cons->fd); - if (tick_is_expired(s->req->analyse_exp, now_ms)) - s->req->flags |= BF_ANA_TIMEOUT; + + if (unlikely(s->rep->flags & (BF_READ_TIMEOUT|BF_WRITE_TIMEOUT))) { + if (s->rep->flags & BF_READ_TIMEOUT) { + buffer_shutw(s->rep); + s->rep->cons->shutr(s->rep->prod); + } + if (s->rep->flags & BF_WRITE_TIMEOUT) { + buffer_shutw(s->rep); + s->rep->cons->shutw(s->rep->cons); + } } /* Note that we don't check nor indicate if we wake up because * of a timeout on a stream interface. diff --git a/src/stream_sock.c b/src/stream_sock.c index 3cdf3f270..efc33a6ef 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -485,8 +485,8 @@ int stream_sock_write(int fd) { } /* - * This function performs a shutdown-write on a stream interface in a connected - * state (it does nothing for other states). It either shuts the write side or + * This function performs a shutdown-write on a stream interface in a connected or + * init state (it does nothing for other states). It either shuts the write side * closes the file descriptor and marks itself as closed. No buffer flags are * changed, it's up to the caller to adjust them. The sole purpose of this * function is to be called from the other stream interface to notify of a @@ -496,7 +496,7 @@ int stream_sock_write(int fd) { */ int stream_sock_shutw(struct stream_interface *si) { - if (si->state != SI_ST_EST) + if (si->state != SI_ST_EST && si->state != SI_ST_CON) return 0; if (si->ib->flags & BF_SHUTR) { @@ -509,6 +509,30 @@ int stream_sock_shutw(struct stream_interface *si) return 0; } +/* + * This function performs a shutdown-read on a stream interface in a connected or + * init state (it does nothing for other states). It either shuts the read side or + * closes the file descriptor and marks itself as closed. No buffer flags are + * changed, it's up to the caller to adjust them. The sole purpose of this + * function is to be called from the other stream interface to notify of a + * close_read, or by itself upon a full write leading to an empty buffer. + * It normally returns zero, unless it has completely closed the socket, in + * which case it returns 1. + */ +int stream_sock_shutr(struct stream_interface *si) +{ + if (si->state != SI_ST_EST && si->state != SI_ST_CON) + return 0; + + if (si->ib->flags & BF_SHUTW) { + fd_delete(si->fd); + si->state = SI_ST_CLO; + return 1; + } + EV_FD_CLR(si->fd, DIR_RD); + return 0; +} + /* * This function only has to be called once after a wakeup event during a data * phase. It controls the file descriptor's status, as well as read and write