MINOR: server: implement a refcount for dynamic servers
It is necessary to have a refcount mechanism on dynamic servers to be
able to enable check support. Indeed, when deleting a dynamic server
with check activated, the check will be asynchronously removed. This is
mandatory to properly free the check resources in a thread-safe manner.
The server instance must be kept alive for this.
(cherry picked from commit d6b7080cecee3450bbad8fbd5d9b100be0a2d13d)
[ad: move refcount increment in 'add server' handler, or else a leak
might be present in case on error return from the handler with the
server already allocated; this bug is not present in upstream because
the increment is now done in new_server directly.]
Signed-off-by: Amaury Denoyelle <adenoyelle@haproxy.com>
diff --git a/include/haproxy/server-t.h b/include/haproxy/server-t.h
index ef91ee9..cd95f9e 100644
--- a/include/haproxy/server-t.h
+++ b/include/haproxy/server-t.h
@@ -258,6 +258,8 @@
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 a9251af..b9f3915 100644
--- a/src/server.c
+++ b/src/server.c
@@ -2203,10 +2203,32 @@
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 <srv> and its member. <srv> 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);
@@ -4428,6 +4450,9 @@
args[1] = sv_name;
errcode = _srv_parse_init(&srv, args, &argc, be, parse_flags, &errmsg);
+ if (srv)
+ srv_use_dynsrv(srv);
+
if (errcode) {
if (errmsg)
cli_dynerr(appctx, errmsg);