#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;
}
}
+/* 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_*.
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;
}
/* 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) {
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)
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);
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;
/* 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:
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;