mirror of
https://github.com/haproxy/haproxy.git
synced 2026-04-22 23:02:34 -04:00
BUG/MEDIUM: lb: Always lock the server when calling server_{take,drop}_conn
The server lock must be held when server_take_conn() and server_drop_conn() lbprm callback functions are called. It is a documented prerequisite but it is not always performed. It only affects leastconn and fas lb algorithm. Others don't use these callback functions. A race condition on the next pending effecive weight (next_eweight) may be encountered with the leastconn lb algorithm. An agent check may set it to 0 while fwlc_srv_reposition() is called. The server is locked during the next_eweight update. But because the server lock is not acquired when fwlc_srv_reposition() is called, we may use it to recompute the server key, leading to a division by 0. This patch must be backported as far as 1.8.
This commit is contained in:
parent
db2c17da60
commit
26a52af642
2 changed files with 12 additions and 3 deletions
|
|
@ -1593,8 +1593,11 @@ int connect_server(struct stream *s)
|
|||
s->flags |= SF_CURR_SESS;
|
||||
count = _HA_ATOMIC_ADD(&srv->cur_sess, 1);
|
||||
HA_ATOMIC_UPDATE_MAX(&srv->counters.cur_sess_max, count);
|
||||
if (s->be->lbprm.server_take_conn)
|
||||
if (s->be->lbprm.server_take_conn) {
|
||||
HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
|
||||
s->be->lbprm.server_take_conn(srv);
|
||||
HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now handle synchronously connected sockets. We know the stream-int
|
||||
|
|
|
|||
10
src/stream.c
10
src/stream.c
|
|
@ -2503,8 +2503,11 @@ void sess_change_server(struct stream *sess, struct server *newsrv)
|
|||
_HA_ATOMIC_SUB(&sess->srv_conn->served, 1);
|
||||
_HA_ATOMIC_SUB(&sess->srv_conn->proxy->served, 1);
|
||||
__ha_barrier_atomic_store();
|
||||
if (sess->srv_conn->proxy->lbprm.server_drop_conn)
|
||||
if (sess->srv_conn->proxy->lbprm.server_drop_conn) {
|
||||
HA_SPIN_LOCK(SERVER_LOCK, &sess->srv_conn->lock);
|
||||
sess->srv_conn->proxy->lbprm.server_drop_conn(sess->srv_conn);
|
||||
HA_SPIN_UNLOCK(SERVER_LOCK, &sess->srv_conn->lock);
|
||||
}
|
||||
stream_del_srv_conn(sess);
|
||||
}
|
||||
|
||||
|
|
@ -2512,8 +2515,11 @@ void sess_change_server(struct stream *sess, struct server *newsrv)
|
|||
_HA_ATOMIC_ADD(&newsrv->served, 1);
|
||||
_HA_ATOMIC_ADD(&newsrv->proxy->served, 1);
|
||||
__ha_barrier_atomic_store();
|
||||
if (newsrv->proxy->lbprm.server_take_conn)
|
||||
if (newsrv->proxy->lbprm.server_take_conn) {
|
||||
HA_SPIN_LOCK(SERVER_LOCK, &newsrv->lock);
|
||||
newsrv->proxy->lbprm.server_take_conn(newsrv);
|
||||
HA_SPIN_UNLOCK(SERVER_LOCK, &newsrv->lock);
|
||||
}
|
||||
stream_add_srv_conn(sess, newsrv);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue