]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: proxy: add lock for global accesses during proxy free
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 2 Mar 2026 07:51:18 +0000 (08:51 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 2 Mar 2026 13:09:25 +0000 (14:09 +0100)
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
src/proxy.c
src/thread.c

index 26b49eaa77fd4e69dfe1291d02b2afef2012d921..50ca683206d9df36cd67a755ca452a3503199146 100644 (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!
index c3293de1fac4079c07bca6a226eeca3fae3dc1ef..39585a31ad6154d270226d9dd06b1e9458812022 100644 (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);
index 7e27ad0097c4d5c38aebcada03c00753542c29a6..985e8c99b4f824af8a06fb924768aa9b6e3555f4 100644 (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";