[master] 7746e30 Keep the fetch thread busyobj pointer-ref separate from the client thread pointer-ref, and deref it on thread scheduling failure.

Martin Blix Grydeland martin at varnish-software.com
Tue Nov 18 13:32:31 CET 2014


commit 7746e30e2c53cf55f0f2525bb3f49c9ee83e9611
Author: Martin Blix Grydeland <martin at varnish-software.com>
Date:   Tue Nov 18 13:12:58 2014 +0100

    Keep the fetch thread busyobj pointer-ref separate from the client
    thread pointer-ref, and deref it on thread scheduling failure.
    
    The code tried to deref the same pointer twice, which failed because
    the VBO_DerefBusyobj() will clear the pointer when called. Separating
    allows calling VBO_DerefBusyobj() for each of them.
    
    Fixes: #1628

diff --git a/bin/varnishd/cache/cache_fetch.c b/bin/varnishd/cache/cache_fetch.c
index 3fae2bf..08f253f 100644
--- a/bin/varnishd/cache/cache_fetch.c
+++ b/bin/varnishd/cache/cache_fetch.c
@@ -904,7 +904,7 @@ void
 VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc,
     struct objcore *oldoc, enum vbf_fetch_mode_e mode)
 {
-	struct busyobj *bo;
+	struct busyobj *bo, *bo_fetch;
 	const char *how;
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
@@ -927,6 +927,7 @@ VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc,
 
 	THR_SetBusyobj(bo);
 
+	bo_fetch = bo;
 	bo->refcount = 2;
 
 	oc->busyobj = bo;
@@ -953,7 +954,7 @@ VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc,
 	AZ(bo->req);
 	bo->req = req;
 
-	bo->fetch_task.priv = bo;
+	bo->fetch_task.priv = bo_fetch;
 	bo->fetch_task.func = vbf_fetch_thread;
 
 	if (Pool_Task(wrk->pool, &bo->fetch_task, POOL_QUEUE_FRONT)) {
@@ -961,17 +962,21 @@ VBF_Fetch(struct worker *wrk, struct req *req, struct objcore *oc,
 		(void)vbf_stp_fail(req->wrk, bo);
 		if (bo->ims_oc != NULL)
 			(void)HSH_DerefObjCore(wrk, &bo->ims_oc);
-		VBO_DerefBusyObj(wrk, &bo);
-	} else if (mode == VBF_BACKGROUND) {
-		VBO_waitstate(bo, BOS_REQ_DONE);
+		VBO_DerefBusyObj(wrk, &bo_fetch);
 	} else {
-		VBO_waitstate(bo, BOS_STREAM);
-		if (bo->state == BOS_FAILED) {
-			AN((oc->flags & OC_F_FAILED));
+		bo_fetch = NULL; /* ref transferred to fetch thread */
+		if (mode == VBF_BACKGROUND) {
+			VBO_waitstate(bo, BOS_REQ_DONE);
 		} else {
-			AZ(bo->fetch_objcore->flags & OC_F_BUSY);
+			VBO_waitstate(bo, BOS_STREAM);
+			if (bo->state == BOS_FAILED) {
+				AN((oc->flags & OC_F_FAILED));
+			} else {
+				AZ(bo->fetch_objcore->flags & OC_F_BUSY);
+			}
 		}
 	}
+	AZ(bo_fetch);
 	VSLb_ts_req(req, "Fetch", W_TIM_real(wrk));
 	VBO_DerefBusyObj(wrk, &bo);
 	THR_SetBusyobj(NULL);



More information about the varnish-commit mailing list