return 1;
}
-/* Returns 0 if the session can keep the idle conn, -1 if it was destroyed. The
- * connection must be private.
+/* Check that session <sess> is able to keep idle connection <conn>. This must
+ * be called after insertion of a private connection into session unless
+ * connection is or will be soon active.
+ *
+ * Returns 0 if the connection is kept or is not attached to the session, else
+ * non-zero if the connection was explicitely removed from session.
*/
static inline int session_check_idle_conn(struct session *sess, struct connection *conn)
{
if (sess->idle_conns >= sess->fe->max_out_conns) {
session_unown_conn(sess, conn);
conn->owner = NULL;
- conn->mux->destroy(conn->ctx);
return -1;
}
else {
*/
HA_ATOMIC_OR(&fconn->wait_event.tasklet->state, TASK_F_USR1);
if (session_check_idle_conn(fconn->conn->owner, fconn->conn) != 0) {
- /* The connection is destroyed, let's leave */
+ fconn->conn->mux->destroy(fconn);
TRACE_DEVEL("outgoing connection killed", FCGI_EV_STRM_END|FCGI_EV_FCONN_ERR);
return;
}
*/
HA_ATOMIC_OR(&h1c->wait_event.tasklet->state, TASK_F_USR1);
if (session_check_idle_conn(sess, h1c->conn)) {
- /* The connection got destroyed, let's leave */
- TRACE_DEVEL("outgoing connection killed", H1_EV_STRM_END|H1_EV_H1C_END);
+ TRACE_DEVEL("outgoing connection rejected", H1_EV_STRM_END|H1_EV_H1C_END, h1c->conn);
+ h1c->conn->mux->destroy(h1c);
goto released;
}
}
*/
HA_ATOMIC_OR(&h2c->wait_event.tasklet->state, TASK_F_USR1);
if (session_check_idle_conn(h2c->conn->owner, h2c->conn) != 0) {
- /* At this point either the connection is destroyed, or it's been added to the server idle list, just stop */
+ h2c->conn->mux->destroy(h2c);
TRACE_DEVEL("leaving without reusable idle connection", H2_EV_STRM_END);
return;
}
if (conn->flags & CO_FL_PRIVATE) {
TRACE_DEVEL("handle private connection reuse", QMUX_EV_STRM_END, conn);
- /* Add connection into session. If an error occured,
- * conn will be closed if idle, or insert will be
- * retried on next detach.
+ /* Ensure conn is attached into session. Most of the times
+ * this is already done during connect so this is a no-op.
*/
if (!session_add_conn(sess, conn)) {
TRACE_ERROR("error during connection insert into session list", QMUX_EV_STRM_END, conn);
conn->owner = NULL;
+
+ /* Session insert failure. Close conn if idle,
+ * else insert will be retry on next detach.
+ */
if (!qcc->nb_sc)
goto release;
}
- /* If conn is idle, check if session can keep it. Conn is freed if this is not the case.
- * TODO graceful shutdown should be preferable instead of plain mux->destroy().
- */
+ /* If conn is idle, check if session can keep it. Conn is closed if this is not the case. */
if (!qcc->nb_sc && session_check_idle_conn(sess, conn)) {
- TRACE_DEVEL("idle conn rejected by session", QMUX_EV_STRM_END);
- conn = NULL;
- goto end;
+ TRACE_DEVEL("idle conn rejected by session", QMUX_EV_STRM_END, conn);
+ goto release;
}
}
else {
*/
HA_ATOMIC_OR(&spop_conn->wait_event.tasklet->state, TASK_F_USR1);
if (session_check_idle_conn(spop_conn->conn->owner, spop_conn->conn) != 0) {
- /* At this point either the connection is destroyed, or it's been added to the server idle list, just stop */
+ spop_conn->conn->mux->destroy(spop_conn);
TRACE_DEVEL("leaving without reusable idle connection", SPOP_EV_STRM_END);
return;
}