[master] 3cf5876 Make a backup-copy of vmod shlibs into the working directory (= -n) so that our compiled VCLs are certain to restart/reload even if the VMOD package has been updated in the meantime.

Poul-Henning Kamp phk at FreeBSD.org
Mon Jan 2 22:46:05 CET 2017


commit 3cf587668219166188e0dce304edb0bf8ab346ab
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Mon Jan 2 21:44:18 2017 +0000

    Make a backup-copy of vmod shlibs into the working directory (= -n)
    so that our compiled VCLs are certain to restart/reload even if
    the VMOD package has been updated in the meantime.
    
    Fixes: #2041

diff --git a/bin/varnishd/cache/cache_vrt_vmod.c b/bin/varnishd/cache/cache_vrt_vmod.c
index b7d7bab..a938568 100644
--- a/bin/varnishd/cache/cache_vrt_vmod.c
+++ b/bin/varnishd/cache/cache_vrt_vmod.c
@@ -34,8 +34,11 @@
 #include "cache.h"
 
 #include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
 
 #include "vcli_serve.h"
 #include "vrt.h"
@@ -54,6 +57,7 @@ struct vmod {
 
 	char			*nm;
 	char			*path;
+	char			*backup;
 	void			*hdl;
 	const void		*funcs;
 	int			funclen;
@@ -61,9 +65,50 @@ struct vmod {
 
 static VTAILQ_HEAD(,vmod)	vmods = VTAILQ_HEAD_INITIALIZER(vmods);
 
+static int
+vrt_vmod_backup_copy(VRT_CTX, const char *nm, const char *fm, const char *to)
+{
+	int fi, fo;
+	int ret = 0;
+	ssize_t sz;
+	char buf[BUFSIZ];
+
+	fo = open(to, O_WRONLY | O_CREAT | O_EXCL, 0744);
+	if (fo < 0 && errno == EEXIST)
+		return (0);
+	if (fo < 0) {
+		VSB_printf(ctx->msg, "Creating copy of vmod %s: %s\n",
+		    nm, strerror(errno));
+		return (1);
+	}
+	fi = open(fm, O_RDONLY);
+	if (fi < 0) {
+		VSB_printf(ctx->msg, "Opening vmod %s from %s: %s\n",
+		    nm, fm, strerror(errno));
+		AZ(unlink(to));
+		AZ(close(fo));
+		return (1);
+	}
+	while (1) {
+		sz = read(fi, buf, sizeof buf);
+		if (sz == 0)
+			break;
+		if (sz < 0 || sz != write(fo, buf, sz)) {
+			VSB_printf(ctx->msg, "Copying vmod %s: %s\n",
+			    nm, strerror(errno));
+			AZ(unlink(to));
+			ret = 1;
+			break;
+		}
+	}
+	AZ(close(fi));
+	AZ(close(fo));
+	return(ret);
+}
+
 int
-VRT_Vmod_Init(struct vmod **hdl, void *ptr, int len, const char *nm,
-    const char *path, const char *file_id, VRT_CTX)
+VRT_Vmod_Init(VRT_CTX, struct vmod **hdl, void *ptr, int len, const char *nm,
+    const char *path, const char *file_id, const char *backup)
 {
 	struct vmod *v;
 	const struct vmod_data *d;
@@ -76,11 +121,18 @@ VRT_Vmod_Init(struct vmod **hdl, void *ptr, int len, const char *nm,
 	AN(hdl);
 	AZ(*hdl);
 
-	dlhdl = dlopen(path, RTLD_NOW | RTLD_LOCAL);
+	/*
+	 * We make a backup copy of the VMOD shlib in our working directory
+	 * and dlopen that, so that we can still restart the VCL's we have
+	 * already compiled when people updated their VMOD package.
+	 */
+	if (vrt_vmod_backup_copy(ctx, nm, path, backup))
+		return (1);
+
+	dlhdl = dlopen(backup, RTLD_NOW | RTLD_LOCAL);
 	if (dlhdl == NULL) {
-		VSB_printf(ctx->msg, "Loading VMOD %s from %s:\n", nm, path);
+		VSB_printf(ctx->msg, "Loading vmod %s from %s:\n", nm, backup);
 		VSB_printf(ctx->msg, "dlopen() failed: %s\n", dlerror());
-		VSB_printf(ctx->msg, "Check child process permissions.\n");
 		return (1);
 	}
 
@@ -90,6 +142,7 @@ VRT_Vmod_Init(struct vmod **hdl, void *ptr, int len, const char *nm,
 	if (v == NULL) {
 		ALLOC_OBJ(v, VMOD_MAGIC);
 		AN(v);
+		REPLACE(v->backup, backup);
 
 		v->hdl = dlhdl;
 
@@ -99,7 +152,7 @@ VRT_Vmod_Init(struct vmod **hdl, void *ptr, int len, const char *nm,
 		    d->file_id == NULL ||
 		    strcmp(d->file_id, file_id)) {
 			VSB_printf(ctx->msg,
-			    "Loading VMOD %s from %s:\n", nm, path);
+			    "Loading vmod %s from %s:\n", nm, path);
 			VSB_printf(ctx->msg,
 			    "This is no longer the same file seen by"
 			    " the VCL-compiler.\n");
@@ -163,6 +216,8 @@ VRT_Vmod_Fini(struct vmod **hdl)
 		return;
 	free(v->nm);
 	free(v->path);
+	AZ(unlink(v->backup));
+	free(v->backup);
 	VTAILQ_REMOVE(&vmods, v, list);
 	VSC_C_main->vmods--;
 	FREE_OBJ(v);
diff --git a/include/vrt.h b/include/vrt.h
index 8668bca..567c49b 100644
--- a/include/vrt.h
+++ b/include/vrt.h
@@ -314,8 +314,8 @@ void VRT_delete_backend(VRT_CTX, struct director **);
 int VRT_VSA_GetPtr(const struct suckaddr *sua, const unsigned char ** dst);
 
 /* VMOD/Modules related */
-int VRT_Vmod_Init(struct vmod **hdl, void *ptr, int len, const char *nm,
-    const char *path, const char *file_id, VRT_CTX);
+int VRT_Vmod_Init(VRT_CTX, struct vmod **hdl, void *ptr, int len,
+    const char *nm, const char *path, const char *file_id, const char *backup);
 void VRT_Vmod_Fini(struct vmod **hdl);
 
 /* VCL program related */
diff --git a/lib/libvcc/vcc_vmod.c b/lib/libvcc/vcc_vmod.c
index af0c7f2..ef2a9e0 100644
--- a/lib/libvcc/vcc_vmod.c
+++ b/lib/libvcc/vcc_vmod.c
@@ -196,7 +196,8 @@ vcc_ParseImport(struct vcc *tl)
 
 	ifp = New_IniFin(tl);
 
-	VSB_printf(ifp->ini, "\tif (VRT_Vmod_Init(&VGC_vmod_%.*s,\n", PF(mod));
+	VSB_printf(ifp->ini, "\tif (VRT_Vmod_Init(ctx,\n");
+	VSB_printf(ifp->ini, "\t    &VGC_vmod_%.*s,\n", PF(mod));
 	VSB_printf(ifp->ini, "\t    &Vmod_%.*s_Func,\n", PF(mod));
 	VSB_printf(ifp->ini, "\t    sizeof(Vmod_%.*s_Func),\n", PF(mod));
 	VSB_printf(ifp->ini, "\t    \"%.*s\",\n", PF(mod));
@@ -206,7 +207,9 @@ vcc_ParseImport(struct vcc *tl)
 	AN(vmd);
 	AN(vmd->file_id);
 	VSB_printf(ifp->ini, "\t    \"%s\",\n", vmd->file_id);
-	VSB_printf(ifp->ini, "\t    ctx))\n");
+	VSB_printf(ifp->ini, "\t    \"./_vmod_%.*s.%s\"\n",
+	    PF(mod), vmd->file_id);
+	VSB_printf(ifp->ini, "\t    ))\n");
 	VSB_printf(ifp->ini, "\t\treturn(1);");
 
 	/* XXX: zero the function pointer structure ?*/
diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py
index 377605b..dff4403 100755
--- a/lib/libvcc/vmodtool.py
+++ b/lib/libvcc/vmodtool.py
@@ -467,7 +467,7 @@ class s_event(stanza):
 	def rstfile(self, fo, man):
 		if len(self.doc) != 0:
 			err("Not emitting .RST for $Event %s\n" %
-                            self.event_func)
+			    self.event_func)
 
 	def hfile(self, fo):
 		fo.write("#ifdef VCL_MET_MAX\n")



More information about the varnish-commit mailing list