[master] 818ca0991 vcp: Poll dying connection pools asynchronously

Nils Goroll nils.goroll at uplex.de
Mon Jan 20 14:41:06 UTC 2025


commit 818ca099105e3ebe1d96fb8deaa91aed6ff1280e
Author: Thibaut Artis <thibaut.artis at varnish-software.com>
Date:   Mon Sep 23 17:45:47 2024 +0200

    vcp: Poll dying connection pools asynchronously
    
    Before, we would wait in a blocking loop for
    connection pools to be freed before deleting
    them for good.
    
    This commit transforms this blocking loop into a
    CLI hook that will delete the freed connection
    pools at each trigger.
    
    Refs #4064
    
    Better diff with the --ignore-all-space option.

diff --git a/bin/varnishd/cache/cache_cli.c b/bin/varnishd/cache/cache_cli.c
index 0a99bc3cf..3670a1bc4 100644
--- a/bin/varnishd/cache/cache_cli.c
+++ b/bin/varnishd/cache/cache_cli.c
@@ -78,6 +78,7 @@ cli_cb_before(const struct cli *cli)
 	VSL(SLT_CLI, NO_VXID, "Rd %s", VSB_data(cli->cmd));
 	Lck_Lock(&cli_mtx);
 	VCL_Poll();
+	VCP_RelPoll();
 }
 
 static void
diff --git a/bin/varnishd/cache/cache_conn_pool.c b/bin/varnishd/cache/cache_conn_pool.c
index 9e940d42d..301e658e3 100644
--- a/bin/varnishd/cache/cache_conn_pool.c
+++ b/bin/varnishd/cache/cache_conn_pool.c
@@ -105,14 +105,20 @@ struct conn_pool {
 };
 
 static struct lock conn_pools_mtx;
+static struct lock dead_pools_mtx;
 
-static VRBT_HEAD(vrb, conn_pool) conn_pools = VRBT_INITIALIZER(&conn_pools);
+VRBT_HEAD(vrb, conn_pool);
 VRBT_GENERATE_REMOVE_COLOR(vrb, conn_pool, entry, static)
 VRBT_GENERATE_REMOVE(vrb, conn_pool, entry, static)
 VRBT_GENERATE_FIND(vrb, conn_pool, entry, vcp_cmp, static)
 VRBT_GENERATE_INSERT_COLOR(vrb, conn_pool, entry, static)
 VRBT_GENERATE_INSERT_FINISH(vrb, conn_pool, entry, static)
 VRBT_GENERATE_INSERT(vrb, conn_pool, entry, vcp_cmp, static)
+VRBT_GENERATE_NEXT(vrb, conn_pool, entry, static);
+VRBT_GENERATE_MINMAX(vrb, conn_pool, entry, static);
+
+static struct vrb conn_pools = VRBT_INITIALIZER(&conn_pools);
+static struct vrb dead_pools = VRBT_INITIALIZER(&dying_cps);
 
 /*--------------------------------------------------------------------
  */
@@ -217,6 +223,22 @@ VCP_AddRef(struct conn_pool *cp)
 	Lck_Unlock(&conn_pools_mtx);
 }
 
+/*--------------------------------------------------------------------
+ */
+
+static void
+vcp_destroy(struct conn_pool **cpp)
+{
+	struct conn_pool *cp;
+
+	TAKE_OBJ_NOTNULL(cp, cpp, CONN_POOL_MAGIC);
+	AZ(cp->n_conn);
+	AZ(cp->n_kill);
+	Lck_Delete(&cp->mtx);
+	free(cp->endpoint);
+	FREE_OBJ(cp);
+}
+
 /*--------------------------------------------------------------------
  * Release Conn pool, destroy if last reference.
  */
@@ -248,17 +270,57 @@ VCP_Rel(struct conn_pool **cpp)
 		(void)shutdown(pfd->fd, SHUT_RDWR);
 		cp->n_kill++;
 	}
-	while (cp->n_kill) {
-		Lck_Unlock(&cp->mtx);
-		(void)usleep(20000);
-		Lck_Lock(&cp->mtx);
-	}
 	Lck_Unlock(&cp->mtx);
-	Lck_Delete(&cp->mtx);
-	AZ(cp->n_conn);
-	AZ(cp->n_kill);
-	free(cp->endpoint);
-	FREE_OBJ(cp);
+	if (cp->n_kill == 0) {
+		vcp_destroy(&cp);
+		return;
+	}
+	Lck_Lock(&dead_pools_mtx);
+	/*
+	 * Here we reuse cp's entry but it will probably not be correctly
+	 * indexed because of the hack in VCP_RelPoll
+	 */
+	VRBT_INSERT(vrb, &dead_pools, cp);
+	Lck_Unlock(&dead_pools_mtx);
+}
+
+void
+VCP_RelPoll(void)
+{
+	struct vrb dead;
+	struct conn_pool *cp, *cp2;
+
+	ASSERT_CLI();
+
+	Lck_Lock(&dead_pools_mtx);
+	if (VRBT_EMPTY(&dead_pools)) {
+		Lck_Unlock(&dead_pools_mtx);
+		return;
+	}
+	dead = dead_pools;
+	VRBT_INIT(&dead_pools);
+	Lck_Unlock(&dead_pools_mtx);
+
+	VRBT_FOREACH_SAFE(cp, vrb, &dead, cp2) {
+		CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
+		if (cp->n_kill > 0)
+			continue;
+		VRBT_REMOVE(vrb, &dead, cp);
+		vcp_destroy(&cp);
+	}
+
+	if (VRBT_EMPTY(&dead))
+		return;
+
+	Lck_Lock(&dead_pools_mtx);
+	/*
+	 * The following insertion will most likely result in an
+	 * unordered tree, but in this case it does not matter
+	 * as we just want to iterate over all the elements
+	 * in the tree in order to delete them.
+	 */
+	VRBT_INSERT(vrb, &dead_pools, dead.rbh_root);
+	Lck_Unlock(&dead_pools_mtx);
 }
 
 /*--------------------------------------------------------------------
@@ -582,6 +644,7 @@ void
 VCP_Init(void)
 {
 	Lck_New(&conn_pools_mtx, lck_conn_pool);
+	Lck_New(&dead_pools_mtx, lck_dead_pool);
 }
 
 /**********************************************************************/
diff --git a/bin/varnishd/cache/cache_varnishd.h b/bin/varnishd/cache/cache_varnishd.h
index a0e4987fa..34a616c8d 100644
--- a/bin/varnishd/cache/cache_varnishd.h
+++ b/bin/varnishd/cache/cache_varnishd.h
@@ -472,6 +472,7 @@ void VSL_Flush(struct vsl_log *, int overflow);
 struct conn_pool;
 void VCP_Init(void);
 void VCP_Panic(struct vsb *, struct conn_pool *);
+void VCP_RelPoll(void);
 
 /* cache_backend_probe.c */
 void VBP_Init(void);
diff --git a/include/tbl/locks.h b/include/tbl/locks.h
index 3de8e33e6..773c31ffa 100644
--- a/include/tbl/locks.h
+++ b/include/tbl/locks.h
@@ -45,6 +45,7 @@ LOCK(pipestat)
 LOCK(probe)
 LOCK(sess)
 LOCK(conn_pool)
+LOCK(dead_pool)
 LOCK(vbe)
 LOCK(vcapace)
 LOCK(vcl)


More information about the varnish-commit mailing list