[MEDIUM] remove stream_sock_update_data()
Two new functions are used instead : buffer_check_{shutr,shutw}.
It is indeed more adequate to check for new closures only when the
buffer reports them.
Several remaining unclosed connections were detected after a test,
even before this patch, so a bug remains. To reproduce, try the
following during 30 seconds :
inject30l4 -n 20000 -l -t 1000 -P 10 -o 4 -u 100 -s 100 -G 127.0.0.1:8000/
diff --git a/src/proto_http.c b/src/proto_http.c
index df905e2..f73964a 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -1136,7 +1136,12 @@
if (s->rep->cons->state != SI_ST_CLO) {
if (((rqf_cli ^ s->req->flags) & BF_MASK_INTERFACE_I) ||
((rpf_cli ^ s->rep->flags) & BF_MASK_INTERFACE_O)) {
- stream_sock_data_update(s->rep->cons->fd);
+
+ if (!(s->rep->flags & BF_SHUTW))
+ buffer_check_shutw(s->rep);
+ if (!(s->req->flags & BF_SHUTR))
+ buffer_check_shutr(s->req);
+
rqf_cli = s->req->flags;
rpf_cli = s->rep->flags;
}
@@ -1175,7 +1180,10 @@
buffer_shutw_now(s->req);
}
- stream_sock_data_update(s->req->cons->fd);
+ if (!(s->req->flags & BF_SHUTW))
+ buffer_check_shutw(s->req);
+ if (!(s->rep->flags & BF_SHUTR))
+ buffer_check_shutr(s->rep);
/* When a server-side connection is released, we have to
* count it and check for pending connections on this server.
diff --git a/src/stream_sock.c b/src/stream_sock.c
index a23d0fd..f7b8d9d 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -471,106 +471,55 @@
/*
* 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
+ * 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_shutw(struct stream_interface *si)
+void stream_sock_shutw(struct stream_interface *si)
{
- if (si->state != SI_ST_EST && si->state != SI_ST_CON)
- return 0;
+ if (si->state != SI_ST_EST && si->state != SI_ST_CON) {
+ if (likely(si->state == SI_ST_INI))
+ si->state = SI_ST_CLO;
+ return;
+ }
if (si->ib->flags & BF_SHUTR) {
fd_delete(si->fd);
si->state = SI_ST_DIS;
- return 1;
+ return;
}
EV_FD_CLR(si->fd, DIR_WR);
shutdown(si->fd, SHUT_WR);
- return 0;
+ return;
}
/*
* 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
+ * 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)
+void stream_sock_shutr(struct stream_interface *si)
{
- if (si->state != SI_ST_EST && si->state != SI_ST_CON)
- return 0;
+ if (si->state != SI_ST_EST && si->state != SI_ST_CON) {
+ if (likely(si->state == SI_ST_INI))
+ si->state = SI_ST_CLO;
+ return;
+ }
if (si->ob->flags & BF_SHUTW) {
fd_delete(si->fd);
si->state = SI_ST_DIS;
- return 1;
+ return;
}
EV_FD_CLR(si->fd, DIR_RD);
- return 0;
+ return;
}
/*
- * Manages a stream_sock connection during its data phase. The buffers are
- * examined for various cases of shutdown, then file descriptor and buffers'
- * flags are updated accordingly.
- */
-int stream_sock_data_update(int fd)
-{
- struct buffer *ib = fdtab[fd].cb[DIR_RD].b;
- struct buffer *ob = fdtab[fd].cb[DIR_WR].b;
-
- DPRINTF(stderr,"[%u] %s: fd=%d owner=%p ib=%p, ob=%p, exp(r,w)=%u,%u ibf=%08x obf=%08x ibl=%d obl=%d si=%d\n",
- now_ms, __FUNCTION__,
- fd, fdtab[fd].owner,
- ib, ob,
- ib->rex, ob->wex,
- ib->flags, ob->flags,
- ib->l, ob->l, ob->cons->state);
-
- /* Check if we need to close the read side */
- if (!(ib->flags & BF_SHUTR)) {
- /* Last read, forced read-shutdown, or other end closed */
- if (ib->flags & (BF_SHUTR_NOW|BF_SHUTW)) {
- //trace_term(t, TT_HTTP_SRV_10);
- buffer_shutr(ib);
- if (ob->flags & BF_SHUTW) {
- fd_delete(fd);
- ob->cons->state = SI_ST_DIS;
- return 0;
- }
- EV_FD_CLR(fd, DIR_RD);
- }
- }
-
- /* Check if we need to close the write side */
- if (!(ob->flags & BF_SHUTW)) {
- /* Forced write-shutdown or other end closed with empty buffer. */
- if ((ob->flags & BF_SHUTW_NOW) ||
- (ob->flags & (BF_EMPTY|BF_HIJACK|BF_WRITE_ENA|BF_SHUTR)) == (BF_EMPTY|BF_WRITE_ENA|BF_SHUTR)) {
- //trace_term(t, TT_HTTP_SRV_11);
- buffer_shutw(ob);
- if (ib->flags & BF_SHUTR) {
- fd_delete(fd);
- ob->cons->state = SI_ST_DIS;
- return 0;
- }
- EV_FD_CLR(fd, DIR_WR);
- shutdown(fd, SHUT_WR);
- }
- }
- return 0; /* other cases change nothing */
-}
-
-
-/*
* Updates a connected stream_sock file descriptor status and timeouts
* according to the buffers' flags. It should only be called once after the
* buffer flags have settled down, and before they are cleared. It doesn't