[master] 36123ef Do a stat(2) check of inode/dev to detect changed vmod files.

Poul-Henning Kamp phk at FreeBSD.org
Mon Aug 25 10:20:40 CEST 2014


commit 36123ef1db0a007fb4dfe5edb485e427a7030da5
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Mon Aug 25 08:20:05 2014 +0000

    Do a stat(2) check of inode/dev to detect changed vmod files.

diff --git a/bin/varnishd/cache/cache_vrt_vmod.c b/bin/varnishd/cache/cache_vrt_vmod.c
index a2dc7c0..b5b76fe 100644
--- a/bin/varnishd/cache/cache_vrt_vmod.c
+++ b/bin/varnishd/cache/cache_vrt_vmod.c
@@ -31,10 +31,14 @@
 
 #include "config.h"
 
+#include <fcntl.h>
 #include <dlfcn.h>
 #include <stdio.h>
 #include <stdlib.h>
 
+#include <sys/types.h>
+#include <sys/stat.h>
+
 #include "cache.h"
 
 #include "vcli_priv.h"
@@ -54,6 +58,8 @@ struct vmod {
 
 	char			*nm;
 	char			*path;
+	intmax_t		st_dev;
+	intmax_t		st_ino;
 	void			*hdl;
 	const void		*funcs;
 	int			funclen;
@@ -69,28 +75,41 @@ VRT_Vmod_Init(void **hdl, void *ptr, int len, const char *nm,
 	const struct vmod_data *d;
 	char buf[256];
 	void *dlhdl;
+	int fd;
+	struct stat st;
 
 	ASSERT_CLI();
 
-	dlhdl = dlopen(path, RTLD_NOW | RTLD_LOCAL);
-	if (dlhdl == NULL) {
+	fd = open(path, O_RDONLY, 0);
+	if (fd < 0) {
 		VCLI_Out(cli, "Loading VMOD %s from %s:\n", nm, path);
-		VCLI_Out(cli, "dlopen() failed: %s\n", dlerror());
+		VCLI_Out(cli, "open() failed: %s\n", strerror(errno));
 		VCLI_Out(cli, "Check child process permissions.\n");
 		return (1);
 	}
 
+	AZ(fstat(fd, &st));
 	VTAILQ_FOREACH(v, &vmods, list)
-		if (v->hdl == dlhdl)
+		if (st.st_dev == v->st_dev && st.st_ino == v->st_ino)
 			break;
-	if (v == NULL) {
-		ALLOC_OBJ(v, VMOD_MAGIC);
-		AN(v);
 
-		v->hdl = dlhdl;
+	if (v != NULL) {
+		AZ(close(fd));
+	} else {
+		dlhdl = fdlopen(fd, RTLD_NOW | RTLD_LOCAL);
+
+		AZ(close(fd));
+
+		if (dlhdl == NULL) {
+			VCLI_Out(cli, "Loading VMOD %s from %s:\n", nm, path);
+			VCLI_Out(cli, "fdlopen() failed: %s\n", dlerror());
+			VCLI_Out(cli, "Check child process permissions.\n");
+			return (1);
+		}
 
 		bprintf(buf, "Vmod_%s_Data", nm);
-		d = dlsym(v->hdl, buf);
+
+		d = dlsym(dlhdl, buf);
 		if (d == NULL ||
 		    d->file_id == NULL ||
 		    strcmp(d->file_id, file_id)) {
@@ -98,10 +117,10 @@ VRT_Vmod_Init(void **hdl, void *ptr, int len, const char *nm,
 			VCLI_Out(cli,
 			    "This is no longer the same file seen by"
 			    " the VCL-compiler.\n");
-			(void)dlclose(v->hdl);
-			FREE_OBJ(v);
+			(void)dlclose(dlhdl);
 			return (1);
 		}
+
 		if (d->vrt_major != VRT_MAJOR_VERSION ||
 		    d->vrt_minor > VRT_MINOR_VERSION ||
 		    d->name == NULL ||
@@ -113,11 +132,17 @@ VRT_Vmod_Init(void **hdl, void *ptr, int len, const char *nm,
 		    d->abi == NULL) {
 			VCLI_Out(cli, "Loading VMOD %s from %s:\n", nm, path);
 			VCLI_Out(cli, "VMOD data is mangled.\n");
-			(void)dlclose(v->hdl);
-			FREE_OBJ(v);
+			(void)dlclose(dlhdl);
 			return (1);
 		}
 
+		ALLOC_OBJ(v, VMOD_MAGIC);
+		AN(v);
+
+		v->st_dev = st.st_dev;
+		v->st_ino = st.st_ino;
+		v->hdl = dlhdl;
+
 		v->funclen = d->func_len;
 		v->funcs = d->func;
 
@@ -143,10 +168,14 @@ VRT_Vmod_Fini(void **hdl)
 
 	ASSERT_CLI();
 
+
 	AN(*hdl);
 	CAST_OBJ_NOTNULL(v, *hdl, VMOD_MAGIC);
 	*hdl = NULL;
 
+	if (--v->ref != 0)
+		return;
+
 #ifndef DONT_DLCLOSE_VMODS
 	/*
 	 * atexit(3) handlers are not called during dlclose(3).  We don't
@@ -155,8 +184,6 @@ VRT_Vmod_Fini(void **hdl)
 	 */
 	AZ(dlclose(v->hdl));
 #endif
-	if (--v->ref != 0)
-		return;
 	free(v->nm);
 	free(v->path);
 	VTAILQ_REMOVE(&vmods, v, list);



More information about the varnish-commit mailing list