Commit 3cf58766 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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
parent 7fcf52f5
......@@ -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);
......
......@@ -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 */
......
......@@ -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 ?*/
......
......@@ -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")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment