[PATCH] Allow vmod objects to trigger initialization failures

Martin Blix Grydeland martin at varnish-software.com
Wed Jun 10 16:36:38 CEST 2015


This allows vmod objects to signal failures if the vmod fails to set
it's object pointer. The VCL will then return early and a VCL
initialization failure is reported.

Also change the deinitialization to only call the fini if the object
pointer is non-NULL.
---
 bin/varnishtest/tests/m00022.vtc   | 30 ++++++++++++++++++++++++++++++
 lib/libvcc/vcc_action.c            | 11 ++++++++++-
 lib/libvmod_debug/vmod.vcc         |  4 ++++
 lib/libvmod_debug/vmod_debug_obj.c | 15 +++++++++++++++
 4 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/bin/varnishtest/tests/m00022.vtc b/bin/varnishtest/tests/m00022.vtc
index c070f19..a173c08 100644
--- a/bin/varnishtest/tests/m00022.vtc
+++ b/bin/varnishtest/tests/m00022.vtc
@@ -14,9 +14,18 @@ varnish v1 -vcl {
 
 	import ${vmod_debug};
 
+	sub vcl_init {
+		new obj = debug.obj("asdf");
+	}
+
 	sub vcl_recv {
 		if (req.url == "/failinit") {
 			debug.set_failinit(1);
+			obj.set_failobj(0);
+			return (synth (200));
+		} else if (req.url == "/failobj") {
+			debug.set_failinit(0);
+			obj.set_failobj(1);
 			return (synth (200));
 		} else {
 			return (synth (404));
@@ -52,3 +61,24 @@ varnish v1 -errvcl {failinit=1} {
 
 	import ${vmod_debug};
 }
+
+# Change to make object init fail
+client c1 {
+	txreq -url /failobj
+	rxresp
+	expect resp.status == 200
+} -run
+
+# Check that object init fails are caught
+varnish v1 -errvcl {failobj=1} {
+	backend default {
+		.host = "${s1_addr}";
+		.port = "${s1_port}";
+	}
+
+	import ${vmod_debug};
+
+	sub vcl_init {
+		new obj = debug.obj("asdf");
+	}
+}
diff --git a/lib/libvcc/vcc_action.c b/lib/libvcc/vcc_action.c
index c4f984d..b70c5ad 100644
--- a/lib/libvcc/vcc_action.c
+++ b/lib/libvcc/vcc_action.c
@@ -220,8 +220,17 @@ parse_new(struct vcc *tl)
 
 	bprintf(buf1, ", &vo_%s, \"%s\"", sy1->name, sy1->name);
 	vcc_Eval_Func(tl, s_init, buf1, sy2->name, s_init + strlen(s_init) + 1);
+
+	Fb(tl, 1, "if (!vo_%s) {\n", sy1->name);
+	tl->indent += INDENT;
+	Fb(tl, 1, "VRT_handling(ctx, VCL_RET_FAIL);\n");
+	Fb(tl, 1, "return (1);\n");
+	tl->indent -= INDENT;
+	Fb(tl, 1, "}\n");
+
 	ifp = New_IniFin(tl);
-	VSB_printf(ifp->fin, "\t%s(&vo_%s);", s_fini, sy1->name);
+	VSB_printf(ifp->fin, "\tif (vo_%s)\n", sy1->name);
+	VSB_printf(ifp->fin, "\t\t%s(&vo_%s);", s_fini, sy1->name);
 	ExpectErr(tl, ';');
 
 	bprintf(buf1, ", vo_%s", sy1->name);
diff --git a/lib/libvmod_debug/vmod.vcc b/lib/libvmod_debug/vmod.vcc
index cbd89a8..8584878 100644
--- a/lib/libvmod_debug/vmod.vcc
+++ b/lib/libvmod_debug/vmod.vcc
@@ -93,6 +93,10 @@ $Method TIME .date()
 
 You never know when you need a date.
 
+$Method VOID .set_failobj(INT)
+
+If set non-zero, the obj vmod object will fail during initialization.
+
 $Function VOID rot52(HTTP hdr)
 
 Encrypt the HTTP header with quad-ROT13 encryption,
diff --git a/lib/libvmod_debug/vmod_debug_obj.c b/lib/libvmod_debug/vmod_debug_obj.c
index 19a966c..7a20495 100644
--- a/lib/libvmod_debug/vmod_debug_obj.c
+++ b/lib/libvmod_debug/vmod_debug_obj.c
@@ -41,6 +41,8 @@ struct vmod_debug_obj {
 	int foobar;
 };
 
+static int failobj = 0;
+
 VCL_VOID
 vmod_obj__init(VRT_CTX, struct vmod_debug_obj **op,
     const char *vcl_name, VCL_STRING s)
@@ -48,6 +50,10 @@ vmod_obj__init(VRT_CTX, struct vmod_debug_obj **op,
 	struct vmod_debug_obj *o;
 
 	CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
+	if (failobj) {
+		VRT_cliout(ctx, "vmod_debug:obj_init:failobj=%u:", failobj);
+		return;
+	}
 	(void)vcl_name;
 	(void)s;
 	AN(op);
@@ -98,3 +104,12 @@ vmod_obj_date(VRT_CTX, struct vmod_debug_obj *o)
 	assert(o->foobar == 42);
 	return (21.4);
 }
+
+VCL_VOID __match_proto__(td_debug_obj_set_failobj)
+vmod_obj_set_failobj(VRT_CTX, struct vmod_debug_obj *o, VCL_INT val)
+{
+
+	(void)ctx;
+	(void)o;
+	failobj = val;
+}
-- 
2.1.4




More information about the varnish-dev mailing list