MEDIUM: proxy: add lock for global accesses during proxy free

Define a new lock with label PROXIES_DEL_LOCK. Its purpose is to protect
operations performed on global lists or trees while a proxy is freed.

Currently, this lock is unneeded as proxies are only freed on
single-thread init or deinit. However, with the incoming dynamic backend
deletion, this operation will be also performed at runtime, outside of
thread isolation.
This commit is contained in:
Amaury Denoyelle 2026-03-02 08:51:18 +01:00
parent a7d1c59a92
commit f58b2698ce
3 changed files with 10 additions and 1 deletions

View File

@ -217,6 +217,7 @@ enum lock_label {
QC_CID_LOCK,
CACHE_LOCK,
GUID_LOCK,
PROXIES_DEL_LOCK,
OTHER_LOCK,
/* WT: make sure never to use these ones outside of development,
* we need them for lock profiling!

View File

@ -68,6 +68,8 @@
#include <haproxy/tools.h>
#include <haproxy/uri_auth.h>
/* Lock to ensure multiple backends deletion concurrently is safe */
static __decl_spinlock(proxies_del_lock);
int listeners; /* # of proxy listeners, set by cfgparse */
struct proxy *proxies_list = NULL; /* list of main proxies */
@ -229,10 +231,15 @@ static inline void proxy_free_common(struct proxy *px)
struct logger *log, *logb;
struct lf_expr *lf, *lfb;
/* First release from global elements under lock protection. */
HA_SPIN_LOCK(PROXIES_DEL_LOCK, &proxies_del_lock);
/* note that the node's key points to p->id */
cebis_item_delete((px->cap & PR_CAP_DEF) ? &defproxy_by_name : &proxy_by_name, conf.name_node, id, px);
ha_free(&px->id);
LIST_DEL_INIT(&px->global_list);
HA_SPIN_UNLOCK(PROXIES_DEL_LOCK, &proxies_del_lock);
/* Now release internal proxy elements. */
ha_free(&px->id);
drop_file_name(&px->conf.file);
counters_fe_shared_drop(&px->fe_counters.shared);
counters_be_shared_drop(&px->be_counters.shared);

View File

@ -439,6 +439,7 @@ const char *lock_label(enum lock_label label)
case QC_CID_LOCK: return "QC_CID";
case CACHE_LOCK: return "CACHE";
case GUID_LOCK: return "GUID";
case PROXIES_DEL_LOCK: return "PROXIES_DEL";
case OTHER_LOCK: return "OTHER";
case DEBUG1_LOCK: return "DEBUG1";
case DEBUG2_LOCK: return "DEBUG2";