mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-20 21:31:28 +02:00
MINOR: muxes: enforce thread-safety for private idle conns
When a backend connnection becomes idle, muxes must activate some protection to mark future access on it as dangerous. Indeed, once a connection is inserted in an idle list, it may be manipulated by another thread, either via takeover or scheduled for purging. Private idle connections are stored into a session instead of the server tree. They are never subject to a takeover for reuse or purge mechanism. As such, currently they do not require the same level of protection. However, a new patch will introduce support for private idle connections purging. Thus, the purpose of this patch is to ensure protection is activated as well now. TASK_F_USR1 was already set on them as an anticipation for such need. Only some extra operations were missing, most notably xprt_set_idle() invokation. Also, return path of muxes detach operation is adjusted to ensure such connection are never accessed after insertion.
This commit is contained in:
parent
b18b5e2f74
commit
9574867358
@ -3748,6 +3748,7 @@ static void fcgi_detach(struct sedesc *sd)
|
||||
* that the handler needs to check it under the idle conns lock.
|
||||
*/
|
||||
HA_ATOMIC_OR(&fconn->wait_event.tasklet->state, TASK_F_USR1);
|
||||
xprt_set_idle(fconn->conn, fconn->conn->xprt, fconn->conn->xprt_ctx);
|
||||
|
||||
/* Ensure session can keep a new idle connection. */
|
||||
if (session_check_idle_conn(sess, fconn->conn) != 0) {
|
||||
@ -3755,6 +3756,13 @@ static void fcgi_detach(struct sedesc *sd)
|
||||
TRACE_DEVEL("outgoing connection killed", FCGI_EV_STRM_END|FCGI_EV_FCONN_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
/* At this point, the connection is inserted into
|
||||
* session list and marked as idle, so it may already
|
||||
* have been purged from another thread.
|
||||
*/
|
||||
TRACE_DEVEL("private connection marked as idle", FCGI_EV_STRM_END, fconn->conn);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1151,6 +1151,8 @@ static int h1s_finish_detach(struct h1s *h1s)
|
||||
* that the handler needs to check it under the idle conns lock.
|
||||
*/
|
||||
HA_ATOMIC_OR(&h1c->wait_event.tasklet->state, TASK_F_USR1);
|
||||
h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event);
|
||||
xprt_set_idle(h1c->conn, h1c->conn->xprt, h1c->conn->xprt_ctx);
|
||||
|
||||
/* Ensure session can keep a new idle connection. */
|
||||
if (session_check_idle_conn(sess, h1c->conn)) {
|
||||
@ -1158,6 +1160,12 @@ static int h1s_finish_detach(struct h1s *h1s)
|
||||
h1c->conn->mux->destroy(h1c);
|
||||
goto released;
|
||||
}
|
||||
|
||||
/* At this point, the connection is inserted into
|
||||
* session list and marked as idle, so it may already
|
||||
* have been purged from another thread.
|
||||
*/
|
||||
goto end;
|
||||
}
|
||||
else {
|
||||
if (h1c->conn->owner == sess)
|
||||
|
@ -5558,6 +5558,7 @@ static void h2_detach(struct sedesc *sd)
|
||||
* that the handler needs to check it under the idle conns lock.
|
||||
*/
|
||||
HA_ATOMIC_OR(&h2c->wait_event.tasklet->state, TASK_F_USR1);
|
||||
xprt_set_idle(h2c->conn, h2c->conn->xprt, h2c->conn->xprt_ctx);
|
||||
|
||||
/* Ensure session can keep a new idle connection. */
|
||||
if (session_check_idle_conn(sess, h2c->conn) != 0) {
|
||||
@ -5565,6 +5566,13 @@ static void h2_detach(struct sedesc *sd)
|
||||
TRACE_DEVEL("leaving without reusable idle connection", H2_EV_STRM_END);
|
||||
return;
|
||||
}
|
||||
|
||||
/* At this point, the connection is inserted into
|
||||
* session list and marked as idle, so it may already
|
||||
* have been purged from another thread.
|
||||
*/
|
||||
TRACE_DEVEL("private connection marked as idle", H2_EV_STRM_END);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -3005,6 +3005,7 @@ static void spop_detach(struct sedesc *sd)
|
||||
* that the handler needs to check it under the idle conns lock.
|
||||
*/
|
||||
HA_ATOMIC_OR(&spop_conn->wait_event.tasklet->state, TASK_F_USR1);
|
||||
xprt_set_idle(spop_conn->conn, spop_conn->conn->xprt, spop_conn->conn->xprt_ctx);
|
||||
|
||||
/* Ensure session can keep a new idle connection. */
|
||||
if (session_check_idle_conn(sess, spop_conn->conn) != 0) {
|
||||
@ -3012,6 +3013,13 @@ static void spop_detach(struct sedesc *sd)
|
||||
TRACE_DEVEL("leaving without reusable idle connection", SPOP_EV_STRM_END);
|
||||
return;
|
||||
}
|
||||
|
||||
/* At this point, the connection is inserted into
|
||||
* session list and marked as idle, so it may already
|
||||
* have been purged from another thread.
|
||||
*/
|
||||
TRACE_DEVEL("private connection marked as idle", SPOP_EV_STRM_END);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user