From f58b2698ce94a2f11bef9ed9ab50941dd6f3ec10 Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Mon, 2 Mar 2026 08:51:18 +0100 Subject: [PATCH] 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. --- include/haproxy/thread-t.h | 1 + src/proxy.c | 9 ++++++++- src/thread.c | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/haproxy/thread-t.h b/include/haproxy/thread-t.h index 26b49eaa7..50ca68320 100644 --- a/include/haproxy/thread-t.h +++ b/include/haproxy/thread-t.h @@ -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! diff --git a/src/proxy.c b/src/proxy.c index c3293de1f..39585a31a 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -68,6 +68,8 @@ #include #include +/* 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); diff --git a/src/thread.c b/src/thread.c index 7e27ad009..985e8c99b 100644 --- a/src/thread.c +++ b/src/thread.c @@ -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";