[master] eb8f35b Close a race condition in the backend/tcp_pools interface.

Poul-Henning Kamp phk at FreeBSD.org
Fri May 15 23:41:22 CEST 2015


commit eb8f35bd79206ff489b895ffb2dc3fb07cabfce5
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Fri May 15 21:40:59 2015 +0000

    Close a race condition in the backend/tcp_pools interface.

diff --git a/bin/varnishd/cache/cache_backend.c b/bin/varnishd/cache/cache_backend.c
index 9aac126..858ade7 100644
--- a/bin/varnishd/cache/cache_backend.c
+++ b/bin/varnishd/cache/cache_backend.c
@@ -135,7 +135,7 @@ vbe_dir_getfd(const struct director *d, struct busyobj *bo)
 	VSLb(bo->vsl, SLT_BackendOpen, "%d %s %s %s %s %s",
 	    vc->fd, bp->display_name, abuf2, pbuf2, abuf1, pbuf1);
 
-	vc->backend->vsc->req++;
+	bp->vsc->req++;
 	INIT_OBJ(bo->htc, HTTP_CONN_MAGIC);
 	bo->htc->vbc = vc;
 	bo->htc->fd = vc->fd;
@@ -167,11 +167,12 @@ vbe_dir_finish(const struct director *d, struct worker *wrk,
 	CHECK_OBJ_NOTNULL(d, DIRECTOR_MAGIC);
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
+	CAST_OBJ_NOTNULL(bp, d->priv, BACKEND_MAGIC);
 
 	CHECK_OBJ_NOTNULL(bo->htc, HTTP_CONN_MAGIC);
 	if (bo->htc->vbc == NULL)
 		return;
-	bp = bo->htc->vbc->backend;
+	bo->htc->vbc->backend = NULL;
 	if (bo->doclose != SC_NULL) {
 		VSLb(bo->vsl, SLT_BackendClose, "%d %s", bo->htc->vbc->fd,
 		    bp->display_name);
@@ -187,8 +188,8 @@ vbe_dir_finish(const struct director *d, struct worker *wrk,
 #define ACCT(foo)	bp->vsc->foo += bo->acct.foo;
 #include "tbl/acct_fields_bereq.h"
 #undef ACCT
-	Lck_Unlock(&bp->mtx);
 	bo->htc->vbc = NULL;
+	Lck_Unlock(&bp->mtx);
 	bo->htc = NULL;
 }
 
diff --git a/bin/varnishd/cache/cache_backend.h b/bin/varnishd/cache/cache_backend.h
index 48dffa4..38a979f 100644
--- a/bin/varnishd/cache/cache_backend.h
+++ b/bin/varnishd/cache/cache_backend.h
@@ -100,6 +100,7 @@ struct vbc {
 	uint8_t			in_waiter;
 	uint8_t			have_been_in_waiter;
 	struct waited		waited[1];
+	struct tcp_pool		*tcp_pool;
 
 	struct backend		*backend;
 };
diff --git a/bin/varnishd/cache/cache_backend_tcp.c b/bin/varnishd/cache/cache_backend_tcp.c
index 5b73e57..518870e 100644
--- a/bin/varnishd/cache/cache_backend_tcp.c
+++ b/bin/varnishd/cache/cache_backend_tcp.c
@@ -85,7 +85,8 @@ tcp_handle(struct waited *w, enum wait_event ev, double now)
 	CAST_OBJ_NOTNULL(vbc, w->ptr, VBC_MAGIC);
 	(void)ev;
 	(void)now;
-	tp = vbc->backend->tcp_pool;			// NB: Incestous
+	CHECK_OBJ_NOTNULL(vbc->tcp_pool, TCP_POOL_MAGIC);
+	tp = vbc->tcp_pool;
 
 	Lck_Lock(&tp->mtx);
 	VSL(SLT_Debug, 0,
@@ -388,6 +389,7 @@ VBT_Get(struct tcp_pool *tp, double tmo)
 		tp->n_conn--;
 		VSC_C_main->backend_reuse += 1;
 		vbc->state = VBC_STATE_USED;
+		assert(vbc->tcp_pool == tp);
 	}
 	tp->n_used++;			// Opening mostly works
 	Lck_Unlock(&tp->mtx);
@@ -399,6 +401,7 @@ VBT_Get(struct tcp_pool *tp, double tmo)
 	AN(vbc);
 	INIT_OBJ(vbc->waited, WAITED_MAGIC);
 	vbc->state = VBC_STATE_USED;
+	vbc->tcp_pool = tp;
 	vbc->fd = VBT_Open(tp, tmo, &vbc->addr);
 	if (vbc->fd < 0)
 		FREE_OBJ(vbc);



More information about the varnish-commit mailing list