[4.0] 2c2eb9b Fix a race i noticed while pondering #1500: We must snapshot the object length while processing the Range header to ensure consistent results when streaming from the backend.

Poul-Henning Kamp phk at FreeBSD.org
Tue Jun 24 11:31:43 CEST 2014


commit 2c2eb9bcf45f75676f91eb6de2a4febd680db716
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Mon May 12 07:26:18 2014 +0000

    Fix a race i noticed while pondering #1500:  We must snapshot the
    object length while processing the Range header to ensure consistent
    results when streaming from the backend.

diff --git a/bin/varnishd/cache/cache_http1_deliver.c b/bin/varnishd/cache/cache_http1_deliver.c
index 765fd83..0b0e138 100644
--- a/bin/varnishd/cache/cache_http1_deliver.c
+++ b/bin/varnishd/cache/cache_http1_deliver.c
@@ -89,10 +89,18 @@ v1d_range_bytes(struct req *req, enum vdp_action act, const void *ptr,
 static void
 v1d_dorange(struct req *req, const char *r)
 {
-	ssize_t low, high, has_low;
+	ssize_t len, low, high, has_low;
 
 	CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
+	CHECK_OBJ_NOTNULL(req->obj, OBJECT_MAGIC);
 	assert(http_GetStatus(req->obj->http) == 200);
+
+	/* We must snapshot the length if we're streaming from the backend */
+	if (req->obj->objcore->busyobj != NULL)
+		len = VBO_waitlen(req->obj->objcore->busyobj, -1);
+	else
+		len = req->obj->len;
+
 	if (strncmp(r, "bytes=", 6))
 		return;
 	r += 6;
@@ -108,7 +116,7 @@ v1d_dorange(struct req *req, const char *r)
 		r++;
 	}
 
-	if (low >= req->obj->len)
+	if (low >= len)
 		return;
 
 	if (*r != '-')
@@ -124,24 +132,24 @@ v1d_dorange(struct req *req, const char *r)
 			r++;
 		}
 		if (!has_low) {
-			low = req->obj->len - high;
+			low = len - high;
 			if (low < 0)
 				low = 0;
-			high = req->obj->len - 1;
+			high = len - 1;
 		}
 	} else
-		high = req->obj->len - 1;
+		high = len - 1;
 	if (*r != '\0')
 		return;
 
-	if (high >= req->obj->len)
-		high = req->obj->len - 1;
+	if (high >= len)
+		high = len - 1;
 
 	if (low > high)
 		return;
 
 	http_PrintfHeader(req->resp, "Content-Range: bytes %jd-%jd/%jd",
-	    (intmax_t)low, (intmax_t)high, (intmax_t)req->obj->len);
+	    (intmax_t)low, (intmax_t)high, (intmax_t)len);
 	http_Unset(req->resp, H_Content_Length);
 	if (req->res_mode & RES_LEN)
 		http_PrintfHeader(req->resp, "Content-Length: %jd",



More information about the varnish-commit mailing list