From: Willy Tarreau Date: Sun, 26 Nov 2017 17:48:14 +0000 (+0100) Subject: BUG/MAJOR: threads/queue: avoid recursive locking in pendconn_get_next_strm() X-Git-Tag: v1.8.0~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=103e5663c8419b1f821ba0d68c1704aeaaec7f91;p=thirdparty%2Fhaproxy.git BUG/MAJOR: threads/queue: avoid recursive locking in pendconn_get_next_strm() pendconn_get_next_strm() is called from process_srv_queue() under the server lock, and calls stream_add_srv_conn() with this lock held, while the latter tries to take it again. This results in a deadlock when a server's maxconn is reached and haproxy is built with thread support. --- diff --git a/include/proto/stream.h b/include/proto/stream.h index 938c58de54..f3fb095ff0 100644 --- a/include/proto/stream.h +++ b/include/proto/stream.h @@ -296,11 +296,16 @@ static void inline stream_inc_http_err_ctr(struct stream *s) } } -static void inline stream_add_srv_conn(struct stream *sess, struct server *srv) +static void inline __stream_add_srv_conn(struct stream *sess, struct server *srv) { - HA_SPIN_LOCK(SERVER_LOCK, &srv->lock); sess->srv_conn = srv; LIST_ADD(&srv->actconns, &sess->by_srv); +} + +static void inline stream_add_srv_conn(struct stream *sess, struct server *srv) +{ + HA_SPIN_LOCK(SERVER_LOCK, &srv->lock); + __stream_add_srv_conn(sess, srv); HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock); } diff --git a/src/queue.c b/src/queue.c index 1796ac147f..1dea7d53ba 100644 --- a/src/queue.c +++ b/src/queue.c @@ -124,7 +124,7 @@ static struct stream *pendconn_get_next_strm(struct server *srv, struct proxy *p /* we want to note that the stream has now been assigned a server */ strm->flags |= SF_ASSIGNED; strm->target = &srv->obj_type; - stream_add_srv_conn(strm, srv); + __stream_add_srv_conn(strm, srv); HA_ATOMIC_ADD(&srv->served, 1); HA_ATOMIC_ADD(&srv->proxy->served, 1); if (px->lbprm.server_take_conn)