[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