]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: connection: provide a common conn_full_close() function
authorWilly Tarreau <w@1wt.eu>
Fri, 23 Nov 2012 16:32:21 +0000 (17:32 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 23 Nov 2012 16:32:21 +0000 (17:32 +0100)
Several places got the connection close sequence wrong because it
was not obvious. In practice we always need the same sequence when
aborting, so let's have a common function for this.

include/proto/connection.h
src/checks.c
src/session.c
src/stream_interface.c

index 4686e7f115f37769f2611a4b8076a8e956eaa16b..3bf337dcbd0c45121595ae1ba12b4d3421cd1fe6 100644 (file)
@@ -26,6 +26,7 @@
 #include <common/memory.h>
 #include <types/connection.h>
 #include <types/listener.h>
+#include <proto/fd.h>
 #include <proto/obj_type.h>
 
 extern struct pool_head *pool2_connection;
@@ -66,6 +67,23 @@ static inline void conn_xprt_close(struct connection *conn)
        }
 }
 
+/* If the connection still has a transport layer, then call its close() function
+ * if any, and delete the file descriptor if a control layer is set. This is
+ * used to close everything at once and atomically. However this is not done if
+ * the CO_FL_XPRT_TRACKED flag is set, which allows logs to take data from the
+ * transport layer very late if needed.
+ */
+static inline void conn_full_close(struct connection *conn)
+{
+       if (conn->xprt && !(conn->flags & CO_FL_XPRT_TRACKED)) {
+               if (conn->xprt->close)
+                       conn->xprt->close(conn);
+               if (conn->ctrl)
+                       fd_delete(conn->t.sock.fd);
+               conn->xprt = NULL;
+       }
+}
+
 /* Update polling on connection <c>'s file descriptor depending on its current
  * state as reported in the connection's CO_FL_CURR_* flags, reports of EAGAIN
  * in CO_FL_WAIT_*, and the sock layer expectations indicated by CO_FL_SOCK_*.
index 530ccd8bcf6da506315dddf90f4c1546dac4101a..e63d34e8c3d3ec3f301279d01199df30ba3b61c6 100644 (file)
@@ -1184,12 +1184,8 @@ static int wake_srv_chk(struct connection *conn)
        if (unlikely(conn->flags & CO_FL_ERROR))
                task_wakeup(s->check.task, TASK_WOKEN_IO);
 
-       if (s->result & (SRV_CHK_FAILED|SRV_CHK_PASSED)) {
-               conn_xprt_close(conn);
-               if (conn->ctrl)
-                       fd_delete(conn->t.sock.fd);
-               conn->ctrl = NULL;
-       }
+       if (s->result & (SRV_CHK_FAILED|SRV_CHK_PASSED))
+               conn_full_close(conn);
        return 0;
 }
 
@@ -1387,10 +1383,7 @@ static struct task *process_chk(struct task *t)
                                /* the check expired and the connection was not
                                 * yet closed, start by doing this.
                                 */
-                               conn_xprt_close(conn);
-                               if (conn->ctrl)
-                                       fd_delete(conn->t.sock.fd);
-                               conn->ctrl = NULL;
+                               conn_full_close(conn);
                        }
 
                        if ((conn->flags & (CO_FL_CONNECTED|CO_FL_WAIT_L4_CONN)) == CO_FL_WAIT_L4_CONN) {
index 9827eb82e6422640a13545273e133eaefdb36040..0a070568b137cad2ff2c1dcf4f3e01bb79bd3a4a 100644 (file)
@@ -249,7 +249,7 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
 static void kill_mini_session(struct session *s)
 {
        /* kill the connection now */
-       conn_xprt_close(s->si[0].conn);
+       conn_full_close(s->si[0].conn);
 
        s->fe->feconn--;
        if (s->stkctr1_entry || s->stkctr2_entry)
@@ -273,11 +273,6 @@ static void kill_mini_session(struct session *s)
        task_delete(s->task);
        task_free(s->task);
 
-       if (fdtab[s->si[0].conn->t.sock.fd].owner)
-               fd_delete(s->si[0].conn->t.sock.fd);
-       else
-               close(s->si[0].conn->t.sock.fd);
-
        pool_free2(pool2_connection, s->si[1].conn);
        pool_free2(pool2_connection, s->si[0].conn);
        pool_free2(pool2_session, s);
index aa8677375b6a21bc19d2f7e84a7bb87f0c166740..e70f0f54dc7bf68e508a3d2fde35fdbbca4944ca 100644 (file)
@@ -227,9 +227,7 @@ int stream_int_shutr(struct stream_interface *si)
                return 0;
 
        if (si->ob->flags & CF_SHUTW) {
-               conn_xprt_close(si->conn);
-               if (conn->ctrl)
-                       fd_delete(si->conn->t.sock.fd);
+               conn_full_close(si->conn);
                si->state = SI_ST_DIS;
                si->exp = TICK_ETERNITY;
 
@@ -318,9 +316,7 @@ int stream_int_shutw(struct stream_interface *si)
                /* we may have to close a pending connection, and mark the
                 * response buffer as shutr
                 */
-               conn_xprt_close(si->conn);
-               if (conn->ctrl)
-                       fd_delete(si->conn->t.sock.fd);
+               conn_full_close(si->conn);
                /* fall through */
        case SI_ST_CER:
        case SI_ST_QUE:
@@ -1166,8 +1162,7 @@ void stream_sock_read0(struct stream_interface *si)
 
  do_close:
        /* OK we completely close the socket here just as if we went through si_shut[rw]() */
-       conn_xprt_close(si->conn);
-       fd_delete(si->conn->t.sock.fd);
+       conn_full_close(si->conn);
 
        si->ib->flags &= ~CF_SHUTR_NOW;
        si->ib->flags |= CF_SHUTR;