[master] 731d208 Slightly polish the vmod loading/unloading code.

Poul-Henning Kamp phk at varnish-cache.org
Wed Sep 18 08:59:24 CEST 2013


commit 731d20843eef23aea1f39d605a02dff18e5d0969
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Wed Sep 18 06:53:14 2013 +0000

    Slightly polish the vmod loading/unloading code.
    
    dlopen/dlclose(3) is deficient in at least two ways, possibly three:
    
    1. It assumes that if the path is the same, the file is the same.
       This makes it impossible to update VMODs in place by any means.
    
    2. It doesn't map the dlopen'ed object in copy-on-write mode.
       This makes things explode if you try anyway, without a rename-guard.
    
    3. It doesn't handle atexit(3) from dlopen(3)'ed code correctly on dlclose(3)
       This makes gcov(1) and friends explode.  The fault could be said to be
       on their part though:  atexit(3) from symlinked code is undefined.
    
    Since there is no sensible way to work around this, live with it, and
    rely on whatever check dlopen(3) uses for identity, rather than have
    our own name-comparison.

diff --git a/bin/varnishd/cache/cache_vrt_vmod.c b/bin/varnishd/cache/cache_vrt_vmod.c
index 84fb105..61e0bd0 100644
--- a/bin/varnishd/cache/cache_vrt_vmod.c
+++ b/bin/varnishd/cache/cache_vrt_vmod.c
@@ -69,24 +69,26 @@ VRT_Vmod_Init(void **hdl, void *ptr, int len, const char *nm,
 	struct vmod *v;
 	void *x, *y, *z, *w;
 	char buf[256];
+	void *dlhdl;
 
 	ASSERT_CLI();
 
+	dlhdl = dlopen(path, RTLD_NOW | RTLD_LOCAL);
+	if (dlhdl == NULL) {
+		VCLI_Out(cli, "Loading VMOD %s from %s:\n", nm, path);
+		VCLI_Out(cli, "dlopen() failed: %s\n", dlerror());
+		VCLI_Out(cli, "Check child process permissions.\n");
+		return (1);
+	}
+
 	VTAILQ_FOREACH(v, &vmods, list)
-		if (!strcmp(v->nm, nm))	// Also path, len ?
+		if (v->hdl == dlhdl)
 			break;
 	if (v == NULL) {
 		ALLOC_OBJ(v, VMOD_MAGIC);
 		AN(v);
 
-		v->hdl = dlopen(path, RTLD_NOW | RTLD_LOCAL);
-		if (v->hdl == NULL) {
-			VCLI_Out(cli, "Loading VMOD %s from %s:\n", nm, path);
-			VCLI_Out(cli, "dlopen() failed: %s\n", dlerror());
-			VCLI_Out(cli, "Check child process permissions.\n");
-			FREE_OBJ(v);
-			return (1);
-		}
+		v->hdl = dlhdl;
 
 		bprintf(buf, "Vmod_%s_Name", nm);
 		x = dlsym(v->hdl, buf);
@@ -158,11 +160,17 @@ VRT_Vmod_Fini(void **hdl)
 	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
+	 * normally use them, but we do when running GCOV.  This option
+	 * enables us to do that.
+	 */
 	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