From: Amaury Denoyelle Date: Mon, 21 Sep 2026 07:05:09 +0000 (+0200) Subject: BUG/MEDIUM: server: remove immediately from GUID tree on delete server X-Git-Tag: v3.5-dev9~226 X-Git-Url: https://git.kaiwu.me/$%7BGITURL%7D$%7Bcid%7D?a=commitdiff_plain;h=d2d4ebbe23e80fcc32e5e125e3e4ff0e4c922024;p=haproxy.git BUG/MEDIUM: server: remove immediately from GUID tree on delete server On "delete server", the target instance is removed from its various attach points in the parent proxy and global collections. The server will then be freed immediately or kept temporarily in the process until its refcount is null. In effect, this means that a server name can be reused immediately after "delete server" success, even if the instance is not immediately freed. This was not the case though with its GUID, as guid_remove() was performed in srv_drop() on null refcount. Changes this behavior so that guid_remove() is now called directly during "delete server" handler. This is better as there is no difference now for server names and GUIDs : both can be reused immediately after the command completion. This could be considered as a bug with a possible backport up to 3.0. Currently it may be better to not pick it unless it becomes mandatory. --- diff --git a/src/guid.c b/src/guid.c index f26f53ea3..f4fd6b705 100644 --- a/src/guid.c +++ b/src/guid.c @@ -83,8 +83,8 @@ int guid_insert(enum obj_type *objt, const char *uid, char **errmsg) return 1; } -/* Remove node from GUID global tree. Must only be called on thread - * isolation. Safe to call even if node is not currently stored. +/* Remove node from GUID global tree. + * Safe to call even if node is not currently stored. */ void guid_remove(struct guid_node *guid) { diff --git a/src/server.c b/src/server.c index 19bd43f79..d68ee1a59 100644 --- a/src/server.c +++ b/src/server.c @@ -3296,8 +3296,6 @@ void srv_drop(struct server *srv) // srv->conf.id.node.leaf_p || // ceb_intree(&srv->name_node)); - guid_remove(&srv->guid); - if (srv->requeue_tasklet) tasklet_kill(srv->requeue_tasklet); task_destroy(srv->warmup); @@ -7022,14 +7020,17 @@ static int cli_parse_delete_server(char **args, char *payload, struct appctx *ap /* Inc proxy refcount until the server is finally freed. */ proxy_take(srv->proxy); - /* remove srv from addr_node tree */ + /* remove srv from proxy trees (IDs, names and addresses) */ if (srv->puid < be->conf.first_unused_id) be->conf.first_unused_id = srv->puid; // search from there for next add. ceb32_item_delete(&be->conf.used_server_id, conf.puid_node, puid, srv); cebuis_item_delete(&be->conf.used_server_name, conf.name_node, id, srv); cebuis_item_delete(&be->used_server_addr, addr_node, addr_key, srv); - /* remove srv from idle_node tree for idle conn cleanup */ + /* remove srv from global GUID tree */ + guid_remove(&srv->guid); + + /* remove srv from global tree for idle conn cleanup */ for (ret = 0; ret < global.nbthread; ret++) eb32_delete(&srv->per_thr[ret].idle_node);