diff --git a/include/haproxy/server-t.h b/include/haproxy/server-t.h index 6772db2b0..02f15fc01 100644 --- a/include/haproxy/server-t.h +++ b/include/haproxy/server-t.h @@ -259,6 +259,8 @@ struct server { unsigned cumulative_weight; /* weight of servers prior to this one in the same group, for chash balancing */ int maxqueue; /* maximum number of pending connections allowed */ + uint refcount_dynsrv; /* refcount used for dynamic servers */ + /* The elements below may be changed on every single request by any * thread, and generally at the same time. */ diff --git a/src/server.c b/src/server.c index 989525761..84b9cd25a 100644 --- a/src/server.c +++ b/src/server.c @@ -2196,10 +2196,32 @@ struct server *new_server(struct proxy *proxy) return srv; } +/* Increment the dynamic server refcount. */ +static void srv_use_dynsrv(struct server *srv) +{ + BUG_ON(!(srv->flags & SRV_F_DYNAMIC)); + HA_ATOMIC_INC(&srv->refcount_dynsrv); +} + +/* Decrement the dynamic server refcount. */ +static uint srv_release_dynsrv(struct server *srv) +{ + BUG_ON(!(srv->flags & SRV_F_DYNAMIC)); + return HA_ATOMIC_SUB_FETCH(&srv->refcount_dynsrv, 1); +} + /* Deallocate a server and its member. must be allocated. */ void free_server(struct server *srv) { + /* For dynamic servers, decrement the reference counter. Only free the + * server when reaching zero. + */ + if (srv->flags & SRV_F_DYNAMIC) { + if (srv_release_dynsrv(srv)) + return; + } + task_destroy(srv->warmup); task_destroy(srv->srvrq_check); @@ -4590,6 +4612,7 @@ static int cli_parse_add_server(char **args, char *payload, struct appctx *appct ebis_insert(&be->conf.used_server_name, &srv->conf.name); ebis_insert(&be->used_server_addr, &srv->addr_node); + srv_use_dynsrv(srv); thread_release(); ha_notice("New server registered.\n");