[4.1] 9754715 Honor first_byte_timeout for recycled backend connections

Dag Haavi Finstad daghf at varnish-software.com
Mon Nov 27 16:36:10 UTC 2017


commit 9754715a4f357a9eb069b0233bf1f36d75626a3b
Author: Dag Haavi Finstad <daghf at varnish-software.com>
Date:   Fri Nov 24 16:22:55 2017 +0100

    Honor first_byte_timeout for recycled backend connections
    
    Fixes: #1772

diff --git a/bin/varnishd/cache/cache_backend.c b/bin/varnishd/cache/cache_backend.c
index 491259c..a6358db 100644
--- a/bin/varnishd/cache/cache_backend.c
+++ b/bin/varnishd/cache/cache_backend.c
@@ -152,7 +152,8 @@ vbe_dir_finish(const struct director *d, struct worker *wrk,
 	CAST_OBJ_NOTNULL(vbc, bo->htc->priv, VBC_MAGIC);
 	bo->htc->priv = NULL;
 	if (vbc->state != VBC_STATE_USED)
-		assert(bo->htc->doclose == SC_TX_PIPE);
+		assert(bo->htc->doclose == SC_TX_PIPE ||
+		    bo->htc->doclose == SC_RX_TIMEOUT);
 	if (bo->htc->doclose != SC_NULL) {
 		VSLb(bo->vsl, SLT_BackendClose, "%d %s", vbc->fd,
 		    bp->display_name);
@@ -210,16 +211,24 @@ vbe_dir_gethdrs(const struct director *d, struct worker *wrk,
 
 		i = V1F_SendReq(wrk, bo, &bo->acct.bereq_hdrbytes, 0);
 
-		if (vbc->state != VBC_STATE_USED)
-			VBT_Wait(wrk, vbc);
-
-		assert(vbc->state == VBC_STATE_USED);
+		if (vbc->state != VBC_STATE_USED) {
+			if (VBT_Wait(wrk, vbc, VTIM_real() +
+			    bo->htc->first_byte_timeout) != 0) {
+				bo->htc->doclose = SC_RX_TIMEOUT;
+				VSLb(bo->vsl, SLT_FetchError,
+				     "Timed out reusing backend connection");
+				extrachance = 0;
+			}
+		}
 
-		if (i == 0)
-			i = V1F_FetchRespHdr(bo);
-		if (i == 0) {
-			AN(bo->htc->priv);
-			return (0);
+		if (bo->htc->doclose == SC_NULL) {
+			assert(vbc->state == VBC_STATE_USED);
+			if (i == 0)
+				i = V1F_FetchRespHdr(bo);
+			if (i == 0) {
+				AN(bo->htc->priv);
+				return (0);
+			}
 		}
 
 		/*
@@ -229,7 +238,7 @@ vbe_dir_gethdrs(const struct director *d, struct worker *wrk,
 		 */
 		vbe_dir_finish(d, wrk, bo);
 		AZ(bo->htc);
-		if (i < 0)
+		if (i < 0 || extrachance == 0)
 			break;
 		if (bo->req != NULL &&
 		    bo->req->req_body_status != REQ_BODY_NONE &&
diff --git a/bin/varnishd/cache/cache_backend.h b/bin/varnishd/cache/cache_backend.h
index d52f2da..65905ed 100644
--- a/bin/varnishd/cache/cache_backend.h
+++ b/bin/varnishd/cache/cache_backend.h
@@ -127,7 +127,7 @@ void VBT_Recycle(const struct worker *, struct tcp_pool *, struct vbc **);
 void VBT_Close(struct tcp_pool *tp, struct vbc **vbc);
 struct vbc *VBT_Get(struct tcp_pool *, double tmo, const struct backend *,
     struct worker *, unsigned force_fresh);
-void VBT_Wait(struct worker *, struct vbc *);
+int VBT_Wait(struct worker *, struct vbc *, double tmo);
 
 /* cache_vcl.c */
 int VCL_AddBackend(struct vcl *, struct backend *);
diff --git a/bin/varnishd/cache/cache_backend_tcp.c b/bin/varnishd/cache/cache_backend_tcp.c
index e80b3c7..49d3175 100644
--- a/bin/varnishd/cache/cache_backend_tcp.c
+++ b/bin/varnishd/cache/cache_backend_tcp.c
@@ -34,6 +34,7 @@
 
 #include "config.h"
 
+#include <errno.h>
 #include <stdlib.h>
 
 #include "cache.h"
@@ -405,10 +406,11 @@ VBT_Get(struct tcp_pool *tp, double tmo, const struct backend *be,
 /*--------------------------------------------------------------------
  */
 
-void
-VBT_Wait(struct worker *wrk, struct vbc *vbc)
+int
+VBT_Wait(struct worker *wrk, struct vbc *vbc, double tmo)
 {
 	struct tcp_pool *tp;
+	int r;
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
 	CHECK_OBJ_NOTNULL(vbc, VBC_MAGIC);
@@ -416,11 +418,23 @@ VBT_Wait(struct worker *wrk, struct vbc *vbc)
 	CHECK_OBJ_NOTNULL(tp, TCP_POOL_MAGIC);
 	assert(vbc->cond == &wrk->cond);
 	Lck_Lock(&tp->mtx);
-	while (vbc->state == VBC_STATE_STOLEN)
-		AZ(Lck_CondWait(&wrk->cond, &tp->mtx, 0));
+
+	while (vbc->state == VBC_STATE_STOLEN) {
+		r = Lck_CondWait(&wrk->cond, &tp->mtx, tmo);
+		if (r != 0) {
+			if (r == EINTR)
+				continue;
+			assert(r == ETIMEDOUT);
+			Lck_Unlock(&tp->mtx);
+			return (1);
+		}
+	}
+
 	assert(vbc->state == VBC_STATE_USED);
 	vbc->cond = NULL;
 	Lck_Unlock(&tp->mtx);
+
+	return (0);
 }
 
 /*--------------------------------------------------------------------*/
diff --git a/bin/varnishtest/tests/r01772.vtc b/bin/varnishtest/tests/r01772.vtc
new file mode 100644
index 0000000..93c5e1b
--- /dev/null
+++ b/bin/varnishtest/tests/r01772.vtc
@@ -0,0 +1,24 @@
+varnishtest "#1772: Honor first_byte_timeout on a recycled connection"
+
+server s1 {
+	rxreq
+	expect req.url == "/first"
+	txresp
+
+	rxreq
+	expect req.url == "/second"
+	delay 2
+	txresp
+} -start
+
+varnish v1 -arg "-p first_byte_timeout=1" -vcl+backend {} -start
+
+client c1 {
+	txreq -url "/first"
+	rxresp
+	expect resp.status == 200
+
+	txreq -url "/second"
+	rxresp
+	expect resp.status == 503
+} -run


More information about the varnish-commit mailing list