]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MEDIUM: server: remove immediately from GUID tree on delete server
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 21 Sep 2026 07:05:09 +0000 (09:05 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 2 Oct 2026 07:41:13 +0000 (09:41 +0200)
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.

src/guid.c
src/server.c

index f26f53ea3093b550a3fe82de97ae282eb67311dd..f4fd6b705e346988c8718372aa011dd03b005ef4 100644 (file)
@@ -83,8 +83,8 @@ int guid_insert(enum obj_type *objt, const char *uid, char **errmsg)
        return 1;
 }
 
-/* Remove <guid> node from GUID global tree. Must only be called on thread
- * isolation. Safe to call even if node is not currently stored.
+/* Remove <guid> node from GUID global tree.
+ * Safe to call even if node is not currently stored.
  */
 void guid_remove(struct guid_node *guid)
 {
index 19bd43f79cd400ec730fdaaa8b5a1d21b8e7b3ba..d68ee1a595fbca2ebd890db9db41fc5df2047aad 100644 (file)
@@ -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);