From f64aa036d8c61101b0828073c6e9148787506d6b Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Mon, 2 Mar 2026 09:05:19 +0100 Subject: [PATCH] MEDIUM: proxy: add lock for global accesses during default free This patch is similar to the previous one, but this time it deals with functions related to defaults proxies instances. Lock PROXIES_DEL_LOCK is used to protect accesses on global collections. This patch will be necessary to implement dynamic backend deletion, even if defaults won't be use as direct target of a "del backend" CLI. However, a backend may have a reference on a default instance. When the backend is freed, this references is released, which can in turn cause the freeing of the default proxy instance. All of this will occur at runtime, outside of thread isolation. --- src/proxy.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/proxy.c b/src/proxy.c index 39585a31a..5779f1672 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -2980,14 +2980,18 @@ static void defaults_px_free(struct proxy *defproxy) /* Removes defaults instance from the name tree, free its content and * storage. This must only be used if is unreferenced. + * + * Uses PROXIES_DEL_LOCK to protect global tree/list accesses. */ void defaults_px_destroy(struct proxy *px) { BUG_ON(!(px->cap & PR_CAP_DEF)); BUG_ON(px->conf.def_ref != 0); + HA_SPIN_LOCK(PROXIES_DEL_LOCK, &proxies_del_lock); cebis_item_delete(&defproxy_by_name, conf.name_node, id, px); LIST_DELETE(&px->el); + HA_SPIN_UNLOCK(PROXIES_DEL_LOCK, &proxies_del_lock); defaults_px_free(px); free(px); @@ -2995,6 +2999,8 @@ void defaults_px_destroy(struct proxy *px) /* delete all unreferenced default proxies. A default proxy is unreferenced if * its count is equal to zero. + * + * Not thread safe - currently only used during init. */ void defaults_px_destroy_all_unref(void) { @@ -3011,6 +3017,8 @@ void defaults_px_destroy_all_unref(void) /* Removes defaults from the name tree. This operation is useful when a * section is made invisible by a newer instance with the same name. If is * not referenced it is freed immediately, else it is kept in defaults_list. + * + * Not thread safe - currently only used during parsing. */ void defaults_px_detach(struct proxy *px) { @@ -3021,7 +3029,10 @@ void defaults_px_detach(struct proxy *px) /* If not destroyed, can still be accessed in . */ } -/* Increments by one defaults proxy reference of all defaults stored in tree name. */ +/* Increments by one defaults proxy reference of all defaults stored in tree name. + * + * Not thread safe - currently only used during init. + */ void defaults_px_ref_all(void) { struct proxy *px; @@ -3033,7 +3044,11 @@ void defaults_px_ref_all(void) } } -/* Decrements defaults proxy ref of all defaults. This is the reverse of defaults_px_ref_all(). */ +/* Decrements defaults proxy ref of all defaults. This is the reverse of + * defaults_px_ref_all(). + * + * Not thread safe - currently only used during deinit. + */ void defaults_px_unref_all(void) { struct proxy *px, *nx; -- 2.47.3