[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