[master] c175ad574 VCP: Fix a race when destroying connection pools

Nils Goroll nils.goroll at uplex.de
Fri Feb 7 11:57:06 UTC 2025


commit c175ad5747ad14545c2938c8d3649d224fa3f1e7
Author: Walid Boudebouda <walid.boudebouda at gmail.com>
Date:   Thu Feb 6 19:08:32 2025 +0100

    VCP: Fix a race when destroying connection pools
    
    Reading n_kill should always be done while holding the
    connection pool mutex, otherwise a race could occur where
    the task cleaning the last connection under the lock would
    set n_kill to 0, and then a context switch would happen before
    it gets a chance to release the lock. This leads to a panic
    in vcp_destroy that tries to Lck_Delete a lock that is still
    being hold.
    
    Fixes #4260

diff --git a/bin/varnishd/cache/cache_conn_pool.c b/bin/varnishd/cache/cache_conn_pool.c
index 300ba66da..bca79783c 100644
--- a/bin/varnishd/cache/cache_conn_pool.c
+++ b/bin/varnishd/cache/cache_conn_pool.c
@@ -248,6 +248,7 @@ VCP_Rel(struct conn_pool **cpp)
 {
 	struct conn_pool *cp;
 	struct pfd *pfd, *pfd2;
+	int n_kill;
 
 	TAKE_OBJ_NOTNULL(cp, cpp, CONN_POOL_MAGIC);
 
@@ -270,8 +271,9 @@ VCP_Rel(struct conn_pool **cpp)
 		(void)shutdown(pfd->fd, SHUT_RDWR);
 		cp->n_kill++;
 	}
+	n_kill = cp->n_kill;
 	Lck_Unlock(&cp->mtx);
-	if (cp->n_kill == 0) {
+	if (n_kill == 0) {
 		vcp_destroy(&cp);
 		return;
 	}
@@ -289,6 +291,7 @@ VCP_RelPoll(void)
 {
 	struct vrb dead;
 	struct conn_pool *cp, *cp2;
+	int n_kill;
 
 	ASSERT_CLI();
 
@@ -303,7 +306,10 @@ VCP_RelPoll(void)
 
 	VRBT_FOREACH_SAFE(cp, vrb, &dead, cp2) {
 		CHECK_OBJ_NOTNULL(cp, CONN_POOL_MAGIC);
-		if (cp->n_kill > 0)
+		Lck_Lock(&cp->mtx);
+		n_kill = cp->n_kill;
+		Lck_Unlock(&cp->mtx);
+		if (n_kill > 0)
 			continue;
 		VRBT_REMOVE(vrb, &dead, cp);
 		vcp_destroy(&cp);


More information about the varnish-commit mailing list