From b71bb6c2aec166a340ae6967731587106c886570 Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Wed, 1 Oct 2025 18:05:53 +0200 Subject: [PATCH] BUG/MEDIUM: fwlc: Handle memory allocation failures. Properly handle memory allocation failures, by checking the return value for pool_alloc(), and if it fails, make sure that the caller will take it into account. The only use of pool_alloc() in fwlc is to allocate the tree elements in order to properly queue the server into the ebtree, so if that allocation fails, just schedule the requeue tasklet, that will try again, until it hopefully eventually succeeds. This should be backported to 3.2. This should fix github issue #3143. --- src/lb_fwlc.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/lb_fwlc.c b/src/lb_fwlc.c index 080745910..20a679e3a 100644 --- a/src/lb_fwlc.c +++ b/src/lb_fwlc.c @@ -165,9 +165,11 @@ static struct fwlc_tree_elt *fwlc_alloc_tree_elt(struct proxy *p, struct fwlc_tr break; } } - if (!allocated_elt) + if (!allocated_elt) { tree_elt = pool_alloc(pool_head_fwlc_elt); - else + if (!tree_elt) + return NULL; + } else tree_elt = allocated_elt; for (i = 0; i < FWLC_LISTS_NB; i++) { @@ -195,6 +197,8 @@ static struct fwlc_tree_elt *fwlc_get_tree_elt(struct server *s, u32 key) if (!tree_elt) { /* No element available, we have to allocate one */ tree_elt = fwlc_alloc_tree_elt(s->proxy, NULL); + if (!tree_elt) + return NULL; tree_elt->lb_node.key = key; eb32_insert(s->lb_tree, &tree_elt->lb_node); } @@ -228,6 +232,17 @@ static inline void fwlc_queue_srv(struct server *s, unsigned int eweight) key = inflight ? (inflight + 1) * SRV_EWGHT_MAX / eweight : 0; tree_elt = fwlc_get_tree_elt(s, key); + if (tree_elt == NULL) { + /* + * We failed to allocate memory for the tree_elt, just stop + * now and schedule the requeue tasklet which will take care + * of the queueing later. + * If the tasklet doesn't exist yet, then there is nothing to + * do, as it will be eventually scheduled after being created. + */ + tasklet_wakeup(s->requeue_tasklet); + return; + } list_nb = statistical_prng_range(FWLC_LISTS_NB); MT_LIST_APPEND(&tree_elt->srv_list[list_nb], &s->lb_mt_list); s->tree_elt = tree_elt; @@ -420,6 +435,14 @@ static void fwlc_srv_reposition(struct server *s) * allocate one and insert it into the tree */ tree_elt = fwlc_alloc_tree_elt(s->proxy, allocated_elt); + if (tree_elt == NULL) { + /* We failed to allocate memory, just try again later */ + HA_RWLOCK_RDUNLOCK(LBPRM_LOCK, &s->proxy->lbprm.lock); + _HA_ATOMIC_STORE(&s->lb_lock, 0); + if (s->requeue_tasklet) + tasklet_wakeup(s->requeue_tasklet); + return; + } if (tree_elt == allocated_elt) allocated_elt = NULL; tree_elt->lb_node.key = new_key; -- 2.47.3