[master] 3abbe2b Universal failure for VRT_purge

Dridi Boukelmoune dridi.boukelmoune at gmail.com
Wed Jun 21 15:15:06 CEST 2017


commit 3abbe2bcdfc671693656564e3dad196b9210370d
Author: Dridi Boukelmoune <dridi.boukelmoune at gmail.com>
Date:   Mon Jun 5 17:28:22 2017 +0200

    Universal failure for VRT_purge
    
    Coverage via a simple debug.purge() wrapper.

diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c
index c69914c..3e88844 100644
--- a/bin/varnishd/cache/cache_vrt.c
+++ b/bin/varnishd/cache/cache_vrt.c
@@ -539,11 +539,17 @@ VRT_purge(VRT_CTX, double ttl, double grace, double keep)
 {
 
 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+
+	if (ctx->method != VCL_MET_HIT && ctx->method != VCL_MET_MISS) {
+		VSLb(ctx->vsl, SLT_VCL_Error,
+		    "purge can only happen in vcl_hit{} or vcl_miss{}");
+		VRT_handling(ctx, VCL_RET_FAIL);
+		return;
+	}
+
 	CHECK_OBJ_NOTNULL(ctx->req, REQ_MAGIC);
 	CHECK_OBJ_NOTNULL(ctx->req->wrk, WORKER_MAGIC);
-	if (ctx->method == VCL_MET_HIT || ctx->method == VCL_MET_MISS)
-		HSH_Purge(ctx->req->wrk, ctx->req->objcore->objhead,
-		    ttl, grace, keep);
+	HSH_Purge(ctx->req->wrk, ctx->req->objcore->objhead, ttl, grace, keep);
 }
 
 /*--------------------------------------------------------------------
diff --git a/bin/varnishtest/tests/r02339.vtc b/bin/varnishtest/tests/r02339.vtc
new file mode 100644
index 0000000..d9e7fbe
--- /dev/null
+++ b/bin/varnishtest/tests/r02339.vtc
@@ -0,0 +1,183 @@
+varnishtest "VMOD purge"
+
+server s1 -repeat 12 {
+	rxreq
+	txresp
+} -start
+
+varnish v1 -arg "-p thread_pools=1" -vcl+backend {
+	import debug;
+
+	sub vcl_recv {
+		if (req.url == "recv") { debug.purge(); }
+		if (req.url == "pass") { return (pass); }
+		if (req.url == "purge") { return (purge); }
+		if (req.url == "synth") { return (synth(200)); }
+	}
+	sub vcl_hash {
+		if (req.url == "hash") { debug.purge(); }
+	}
+	sub vcl_miss {
+		if (req.url == "miss") { debug.purge(); }
+	}
+	sub vcl_hit {
+		if (req.url == "hit") { debug.purge(); }
+	}
+	sub vcl_purge {
+		if (req.url == "purge") { debug.purge(); }
+	}
+	sub vcl_pass {
+		if (req.url == "pass") { debug.purge(); }
+	}
+	sub vcl_deliver {
+		if (req.url == "deliver") { debug.purge(); }
+	}
+	sub vcl_synth {
+		if (req.url == "synth") { debug.purge(); }
+	}
+	sub vcl_backend_fetch {
+		if (bereq.url == "fetch") { debug.purge(); }
+		if (bereq.url == "error") {
+			set bereq.backend = debug.no_backend();
+		}
+	}
+	sub vcl_backend_error {
+		if (bereq.url == "error") { debug.purge(); }
+	}
+	sub vcl_backend_response {
+		if (bereq.url == "response") { debug.purge(); }
+	}
+} -start
+
+logexpect l0 -v v1 -g raw {
+	expect * 0 ExpKill	"EXP_Expired x=1002"
+} -start
+
+logexpect l1 -v v1 {
+	expect * 1002	Begin		"bereq 1001 fetch"
+
+	expect * 1003	VCL_call	HIT
+	expect * =	VCL_Log		PURGE
+	expect * =	VCL_call	DELIVER
+
+	expect * 1004	VCL_call	MISS
+	expect * =	VCL_Log		PURGE
+	expect * =	VCL_call	DELIVER
+
+	expect * 1007	VCL_call	RECV
+	expect * =	VCL_Log		PURGE
+	expect * =	VCL_Error	purge
+	expect * =	VCL_return	fail
+
+	expect * 1009	VCL_call	HASH
+	expect * =	VCL_Log		PURGE
+	expect * =	VCL_Error	purge
+	expect * =	VCL_return	fail
+
+	expect * 1011	VCL_call	PURGE
+	expect * =	VCL_Log		PURGE
+	expect * =	VCL_Error	purge
+
+	expect * 1013	VCL_call	PASS
+	expect * =	VCL_Log		PURGE
+	expect * =	VCL_Error	purge
+
+	expect * 1015	VCL_call	DELIVER
+	expect * =	VCL_Log		PURGE
+	expect * =	VCL_Error	purge
+
+	expect * 1018	VCL_call	SYNTH
+	expect * =	VCL_Log		PURGE
+	expect * =	VCL_Error	purge
+
+	expect * 1021	VCL_call	BACKEND_FETCH
+	expect * =	VCL_Log		PURGE
+	expect * =	VCL_Error	purge
+
+	expect * 1024	VCL_call	BACKEND_ERROR
+	expect * =	VCL_Log		PURGE
+	expect * =	VCL_Error	purge
+
+	expect * 1027	VCL_call	BACKEND_RESPONSE
+	expect * =	VCL_Log		PURGE
+	expect * =	VCL_Error	purge
+} -start
+
+client c1 {
+	txreq -url hit
+	rxresp
+	expect resp.status == 200
+
+	txreq -url hit
+	rxresp
+	expect resp.status == 200
+
+	txreq -url miss
+	rxresp
+	expect resp.status == 200
+} -run
+
+logexpect l0 -wait
+
+client c1 {
+	txreq -url recv
+	rxresp
+	expect resp.status == 503
+	expect_close
+} -run
+
+client c1 {
+	txreq -url hash
+	rxresp
+	expect resp.status == 503
+	expect_close
+} -run
+
+client c1 {
+	txreq -url purge
+	rxresp
+	expect resp.status == 503
+	expect_close
+} -run
+
+client c1 {
+	txreq -url pass
+	rxresp
+	expect resp.status == 503
+	expect_close
+} -run
+
+client c1 {
+	txreq -url deliver
+	rxresp
+	expect resp.status == 503
+	expect_close
+} -run
+
+client c1 {
+	txreq -url synth
+	expect_close
+} -run
+
+client c1 {
+	txreq -url fetch
+	rxresp
+	expect resp.status == 503
+	expect_close
+} -run
+
+client c1 {
+	txreq -url error
+	rxresp
+	expect resp.status == 503
+	expect_close
+} -run
+
+client c1 {
+	txreq -url response
+	rxresp
+	expect resp.status == 503
+	expect_close
+} -run
+
+logexpect l1 -wait
diff --git a/doc/changes.rst b/doc/changes.rst
index eef34c2..436b4e0 100644
--- a/doc/changes.rst
+++ b/doc/changes.rst
@@ -6,6 +6,9 @@ Varnish Cache Trunk (ongoing)
 
 * On platforms with setproctitle(3), use the -i argument rather than -n
 
+* VRT_purge fails a transaction if used outside of ``vcl_hit`` and
+  ``vcl_miss`` (#2339)
+
 * VSM_Name() returns the -i argument name, rather than the -n name.
 
 * VUT.name is goine, use VSM_Name(VUT.vsm)
diff --git a/include/vrt.h b/include/vrt.h
index b8377f3..3308634 100644
--- a/include/vrt.h
+++ b/include/vrt.h
@@ -41,6 +41,7 @@
  *
  * 6.1 (unreleased):
  *	http_CollectHdrSep added
+ *	VRT_purge modified (may fail a transaction)
  * 6.0 (2017-03-15):
  *	VRT_hit_for_pass added
  *	VRT_ipcmp added
diff --git a/lib/libvmod_debug/vmod.vcc b/lib/libvmod_debug/vmod.vcc
index b33d3af..9323488 100644
--- a/lib/libvmod_debug/vmod.vcc
+++ b/lib/libvmod_debug/vmod.vcc
@@ -219,3 +219,7 @@ Returns the size in bytes of a collection of C-datatypes.
 * 'z' = size_t
 * 'o' = off_t
 * 'j' = intmax_t
+
+$Function VOID purge(DURATION ttl = 0, DURATION grace = 0, DURATION keep = 0)
+
+Performs a purge, by default a hard purge where ttl, grace and keep are zero.
diff --git a/lib/libvmod_debug/vmod_debug.c b/lib/libvmod_debug/vmod_debug.c
index d22c1a1..d8e2910 100644
--- a/lib/libvmod_debug/vmod_debug.c
+++ b/lib/libvmod_debug/vmod_debug.c
@@ -572,3 +572,13 @@ vmod_typesize(VRT_CTX, VCL_STRING s)
 	}
 	return ((VCL_INT)i);
 }
+
+VCL_VOID
+vmod_purge(VRT_CTX, double ttl, double grace, double keep)
+{
+
+	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+
+	VSLb(ctx->vsl, SLT_VCL_Log, "PURGE");
+	VRT_purge(ctx, ttl, grace, keep);
+}



More information about the varnish-commit mailing list