]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] remove stream_sock_update_data()
authorWilly Tarreau <w@1wt.eu>
Sun, 23 Nov 2008 18:31:35 +0000 (19:31 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 23 Nov 2008 18:31:35 +0000 (19:31 +0100)
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/

include/proto/buffers.h
include/proto/stream_sock.h
include/types/buffers.h
include/types/stream_interface.h
src/proto_http.c
src/stream_sock.c

index 36a82d8de4bdbd5b97ba9393c95ad9bb1b83cf23..7d1bb11ac14b552fa583b28f33375b4202353c59 100644 (file)
@@ -3,7 +3,7 @@
   Buffer management definitions, macros and inline functions.
 
   Copyright (C) 2000-2008 Willy Tarreau - w@1wt.eu
-  
+
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation, version 2.1
@@ -150,6 +150,46 @@ static inline void buffer_write_dis(struct buffer *buf)
        buf->flags &= ~BF_WRITE_ENA;
 }
 
+/* check if the buffer needs to be shut down for read, and perform the shutdown
+ * at the stream_interface level if needed. This must not be used with a buffer
+ * for which a connection is currently in queue or turn-around.
+ */
+static inline void buffer_check_shutr(struct buffer *b)
+{
+       if (b->flags & BF_SHUTR)
+               return;
+
+       if (!(b->flags & (BF_SHUTR_NOW|BF_SHUTW)))
+               return;
+
+       /* Last read, forced read-shutdown, or other end closed. We have to
+        * close our read side and inform the stream_interface.
+        */
+       buffer_shutr(b);
+       b->prod->shutr(b->prod);
+}
+
+/* check if the buffer needs to be shut down for write, and perform the shutdown
+ * at the stream_interface level if needed. This must not be used with a buffer
+ * for which a connection is currently in queue or turn-around.
+ */
+static inline void buffer_check_shutw(struct buffer *b)
+{
+       if (b->flags & BF_SHUTW)
+               return;
+
+       if ((b->flags & BF_SHUTW_NOW) ||
+           (b->flags & (BF_EMPTY|BF_HIJACK|BF_WRITE_ENA|BF_SHUTR)) ==
+           (BF_EMPTY|BF_WRITE_ENA|BF_SHUTR)) {
+               /* Application requested write-shutdown, or other end closed
+                * with empty buffer. We have to close our write side and
+                * inform the stream_interface.
+                */
+               buffer_shutw(b);
+               b->cons->shutw(b->cons);
+       }
+}
+
 /* returns the maximum number of bytes writable at once in this buffer */
 static inline int buffer_max(const struct buffer *buf)
 {
index ddad638254ee3c02ca9189b10524c6cfb732597a..a7bcb9937b01acb780f39aaf9b34033bb993b008 100644 (file)
 /* main event functions used to move data between sockets and buffers */
 int stream_sock_read(int fd);
 int stream_sock_write(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);
+void stream_sock_shutr(struct stream_interface *si);
+void stream_sock_shutw(struct stream_interface *si);
 
 
 /* This either returns the sockname or the original destination address. Code
index 7e72c28e1d2c1d496ae95c52464b2357860e4da9..ddfb2771cf5cda8ca0daa221386d656dc8b4470d 100644 (file)
@@ -3,7 +3,7 @@
   Buffer management definitions, macros and inline functions.
 
   Copyright (C) 2000-2008 Willy Tarreau - w@1wt.eu
-  
+
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation, version 2.1
@@ -24,6 +24,7 @@
 
 #include <common/config.h>
 #include <common/memory.h>
+#include <types/stream_interface.h>
 
 /* The BF_* macros designate Buffer Flags, which may be ORed in the bit field
  * member 'flags' in struct buffer. Here we have several types of flags :
index 111ffc740c67a68ce30efa4fa9d3e2ea6a72ec50..ffaf8ad65cbf24f51ee1660e7223798a115f483f 100644 (file)
@@ -74,8 +74,8 @@ struct stream_interface {
        int fd;                 /* file descriptor for a stream driver when known */
        unsigned int flags;     /* SI_FL_*, must be cleared before I/O */
        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 */
+       void (*shutr)(struct stream_interface *);  /* shutr function */
+       void (*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_* */
        void *err_loc;          /* commonly the server, NULL when SI_ET_NONE */
index df905e27138b155f78355fd104e717d4d25325a8..f73964a3c59b6ae1ddc1ca5d07ed82f8bab9d87b 100644 (file)
@@ -1136,7 +1136,12 @@ void process_session(struct task *t, int *next)
                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 @@ void process_session(struct task *t, int *next)
                                                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.
index a23d0fd321778759c1669f19ba3d94b87e4b6ffd..f7b8d9d85a2f641121b8a6a5f1c1b8efaabcdcc5 100644 (file)
@@ -471,105 +471,54 @@ int stream_sock_write(int fd) {
 /*
  * 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;
-}
-
-/*
- * 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 */
+       return;
 }
 
-
 /*
  * Updates a connected stream_sock file descriptor status and timeouts
  * according to the buffers' flags. It should only be called once after the