mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 23:27:04 +02:00
BUG/MAJOR: leastconn: do not loop forever when facing saturated servers
Since commit 9fe72bba3
("MAJOR: leastconn; Revamp the way servers are
ordered."), there's no way to escape the loop visiting the mt_list heads
in fwlc_get_next_server if all servers in the list are saturated,
resulting in a watchdog panic. It can be reproduced with this config
and injecting with more than 2 concurrent conns:
balance leastconn
server s1 127.0.0.1:8000 maxconn 1
server s2 127.0.0.1:8000 maxconn 1
Here we count the number of saturated servers that were encountered, and
escape the loop once the number of remaining servers exceeds the number
of saturated ones. No backport is needed since this arrived in 3.2.
This commit is contained in:
parent
ccc65012d3
commit
6be02d1c6e
@ -762,13 +762,14 @@ struct server *fwlc_get_next_server(struct proxy *p, struct server *srvtoavoid)
|
|||||||
while (node) {
|
while (node) {
|
||||||
struct fwlc_tree_elt *tree_elt;
|
struct fwlc_tree_elt *tree_elt;
|
||||||
struct server *s;
|
struct server *s;
|
||||||
|
int unusable = 0;
|
||||||
int orig_nb;
|
int orig_nb;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
tree_elt = eb32_entry(node, struct fwlc_tree_elt, lb_node);
|
tree_elt = eb32_entry(node, struct fwlc_tree_elt, lb_node);
|
||||||
orig_nb = statistical_prng_range(FWLC_LISTS_NB);
|
orig_nb = statistical_prng_range(FWLC_LISTS_NB);
|
||||||
|
|
||||||
while (_HA_ATOMIC_LOAD(&tree_elt->elements) > 0) {
|
while (_HA_ATOMIC_LOAD(&tree_elt->elements) > unusable) {
|
||||||
struct mt_list mt_list;
|
struct mt_list mt_list;
|
||||||
mt_list.next = _HA_ATOMIC_LOAD(&tree_elt->srv_list[(i + orig_nb) % FWLC_LISTS_NB].next);
|
mt_list.next = _HA_ATOMIC_LOAD(&tree_elt->srv_list[(i + orig_nb) % FWLC_LISTS_NB].next);
|
||||||
|
|
||||||
@ -802,6 +803,8 @@ struct server *fwlc_get_next_server(struct proxy *p, struct server *srvtoavoid)
|
|||||||
}
|
}
|
||||||
avoided = s;
|
avoided = s;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
unusable++;
|
||||||
i++;
|
i++;
|
||||||
} else if (mt_list.next == &tree_elt->srv_list[(i + orig_nb) % FWLC_LISTS_NB]) {
|
} else if (mt_list.next == &tree_elt->srv_list[(i + orig_nb) % FWLC_LISTS_NB]) {
|
||||||
i++;
|
i++;
|
||||||
|
Loading…
Reference in New Issue
Block a user