[master] 2c4e481 Use libumem only as a storage allocator, not to override malloc etc.

Nils Goroll nils.goroll at uplex.de
Wed Apr 4 14:49:11 UTC 2018


commit 2c4e481ed1e7ddfc8cc04233cea53b0942340ab2
Author: Geoff Simmons <geoff at uplex.de>
Date:   Mon Apr 2 22:05:05 2018 +0200

    Use libumem only as a storage allocator, not to override malloc etc.
    
    We do this by not linking with libumem, but rather using dlopen/dlsym
    to load the slab allocator interface, which is used by the stevedore.

diff --git a/bin/varnishd/Makefile.am b/bin/varnishd/Makefile.am
index 739b16c..1e8640e 100644
--- a/bin/varnishd/Makefile.am
+++ b/bin/varnishd/Makefile.am
@@ -169,7 +169,7 @@ varnishd_LDADD = \
 	@SAN_LDFLAGS@ \
 	@JEMALLOC_LDADD@ \
 	@PCRE_LIBS@ \
-	${DL_LIBS} ${PTHREAD_LIBS} ${NET_LIBS} ${RT_LIBS} ${LIBM} ${UMEM_LIBS}
+	${DL_LIBS} ${PTHREAD_LIBS} ${NET_LIBS} ${RT_LIBS} ${LIBM}
 
 noinst_PROGRAMS = vhp_gen_hufdec
 vhp_gen_hufdec_SOURCES = hpack/vhp_gen_hufdec.c
diff --git a/bin/varnishd/mgt/mgt_main.c b/bin/varnishd/mgt/mgt_main.c
index 05b4c61..237a45b 100644
--- a/bin/varnishd/mgt/mgt_main.c
+++ b/bin/varnishd/mgt/mgt_main.c
@@ -136,7 +136,7 @@ usage(void)
 
 	printf(FMT, "-s [name=]kind[,options]", "Storage specification");
 	printf(FMT, "", "Can be specified multiple times.");
-#ifdef HAVE_LIBUMEM
+#ifdef HAVE_UMEM_H
 	printf(FMT, "", "  -s default (=umem)");
 	printf(FMT, "", "  -s umem");
 #else
diff --git a/bin/varnishd/storage/mgt_stevedore.c b/bin/varnishd/storage/mgt_stevedore.c
index ba7e5b1..a37ddf3 100644
--- a/bin/varnishd/storage/mgt_stevedore.c
+++ b/bin/varnishd/storage/mgt_stevedore.c
@@ -126,7 +126,7 @@ static const struct choice STV_choice[] = {
 	{ "deprecated_persistent",	&smp_stevedore },
 	{ "persistent",			&smp_fake_stevedore },
 #endif
-#if defined(HAVE_LIBUMEM)
+#if defined(HAVE_UMEM_H)
 	{ "umem",			&smu_stevedore },
 	{ "default",			&smu_stevedore },
 #else
diff --git a/bin/varnishd/storage/storage_umem.c b/bin/varnishd/storage/storage_umem.c
index afc2771..acb291a 100644
--- a/bin/varnishd/storage/storage_umem.c
+++ b/bin/varnishd/storage/storage_umem.c
@@ -33,13 +33,14 @@
 
 #include "config.h"
 
-#if defined(HAVE_LIBUMEM)
+#if defined(HAVE_UMEM_H)
 
 #include "cache/cache_varnishd.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <umem.h>
+#include <dlfcn.h>
 
 #include "storage/storage.h"
 #include "storage/storage_simple.h"
@@ -67,6 +68,30 @@ struct smu {
 	struct smu_sc		*sc;
 };
 
+/*
+ * We only want the umem slab allocator for cache storage, not also as a
+ * substitute for malloc and friends. So we don't link with libumem, but
+ * use dlopen/dlsym to get the slab allocator interface into function
+ * pointers.
+ */
+typedef void * (*umem_alloc_f)(size_t size, int flags);
+typedef void (*umem_free_f)(void *buf, size_t size);
+typedef umem_cache_t * (*umem_cache_create_f)(char *debug_name, size_t bufsize,
+    size_t align, umem_constructor_t *constructor,
+    umem_destructor_t *destructor, umem_reclaim_t *reclaim,
+    void *callback_data, vmem_t *source, int cflags);
+typedef void (*umem_cache_destroy_f)(umem_cache_t *cache);
+typedef void * (*umem_cache_alloc_f)(umem_cache_t *cache, int flags);
+typedef void (*umem_cache_free_f)(umem_cache_t *cache, void *buffer);
+
+static void *libumem_hndl = NULL;
+static umem_alloc_f umem_allocf = NULL;
+static umem_free_f umem_freef = NULL;
+static umem_cache_create_f umem_cache_createf = NULL;
+static umem_cache_destroy_f umem_cache_destroyf = NULL;
+static umem_cache_alloc_f umem_cache_allocf = NULL;
+static umem_cache_free_f umem_cache_freef = NULL;
+
 /* init required per cache get:
    smu->sz = size
    smu->s.ptr;
@@ -142,14 +167,14 @@ smu_alloc(const struct stevedore *st, size_t size)
 	 * allocations growing another full page, just to accommodate the smu.
 	 */
 
-	p = umem_alloc(size, UMEM_DEFAULT);
+	p = umem_allocf(size, UMEM_DEFAULT);
 	if (p != NULL) {
 		AN(smu_sc->smu_cache);
-		smu = umem_cache_alloc(smu_sc->smu_cache, UMEM_DEFAULT);
+		smu = umem_cache_allocf(smu_sc->smu_cache, UMEM_DEFAULT);
 		if (smu != NULL)
 			smu->s.ptr = p;
 		else
-			umem_free(p, size);
+			umem_freef(p, size);
 	}
 	if (smu == NULL) {
 		Lck_Lock(&smu_sc->smu_mtx);
@@ -191,9 +216,9 @@ smu_free(struct storage *s)
 		sc->stats->g_space += smu->sz;
 	Lck_Unlock(&sc->smu_mtx);
 
-	umem_free(smu->s.ptr, smu->sz);
+	umem_freef(smu->s.ptr, smu->sz);
 	smu_smu_init(smu, sc);
-	umem_cache_free(sc->smu_cache, smu);
+	umem_cache_freef(sc->smu_cache, smu);
 }
 
 static VCL_BYTES v_matchproto_(stv_var_used_space)
@@ -235,6 +260,28 @@ smu_init(struct stevedore *parent, int ac, char * const *av)
 	if (ac == 0 || *av[0] == '\0')
 		 return;
 
+	/* Check if these load in the management process. */
+	(void) dlerror();
+	if ((libumem_hndl = dlopen("libumem.so", RTLD_NOW)) == NULL)
+		ARGV_ERR("(-sumem) cannot open libumem.so: %s", dlerror());
+
+#define DLSYM_UMEM(fptr,sym)						\
+	do {								\
+		(void) dlerror();					\
+		if ((fptr = dlsym(libumem_hndl, #sym)) == NULL)		\
+			ARGV_ERR("(-sumem) cannot find symbol " #sym ": %s", \
+			    dlerror());					\
+	} while(0)
+
+	DLSYM_UMEM(umem_allocf, umem_alloc);
+	DLSYM_UMEM(umem_freef, umem_free);
+	DLSYM_UMEM(umem_cache_createf, umem_cache_create);
+	DLSYM_UMEM(umem_cache_destroyf, umem_cache_destroy);
+	DLSYM_UMEM(umem_cache_allocf, umem_cache_alloc);
+	DLSYM_UMEM(umem_cache_freef, umem_cache_free);
+
+#undef DLSYM_UMEM
+
 	e = VNUM_2bytes(av[0], &u, 0);
 	if (e != NULL)
 		ARGV_ERR("(-sumem) size \"%s\": %s\n", av[0], e);
@@ -262,7 +309,32 @@ smu_open(struct stevedore *st)
 	if (smu_sc->smu_max != SIZE_MAX)
 		smu_sc->stats->g_space = smu_sc->smu_max;
 
-	smu_sc->smu_cache = umem_cache_create(st->ident,
+	/*
+	 * Load the symbols for use in the child process, assert if they
+	 * fail to load.
+	 */
+	if (libumem_hndl == NULL) {
+		libumem_hndl = dlopen("libumem.so", RTLD_NOW);
+		AN(libumem_hndl);
+
+#define DLSYM_UMEM(fptr,sym)					\
+		do {						\
+			fptr = dlsym(libumem_hndl, #sym);	\
+			AN(fptr);				\
+		} while(0)
+
+	DLSYM_UMEM(umem_allocf, umem_alloc);
+	DLSYM_UMEM(umem_freef, umem_free);
+	DLSYM_UMEM(umem_cache_createf, umem_cache_create);
+	DLSYM_UMEM(umem_cache_destroyf, umem_cache_destroy);
+	DLSYM_UMEM(umem_cache_allocf, umem_cache_alloc);
+	DLSYM_UMEM(umem_cache_freef, umem_cache_free);
+
+#undef DLSYM_UMEM
+
+	}
+
+	smu_sc->smu_cache = umem_cache_createf(st->ident,
 					  sizeof(struct smu),
 					  0,		// align
 					  smu_smu_constructor,
@@ -285,7 +357,7 @@ smu_close(const struct stevedore *st, int warn)
 	CAST_OBJ_NOTNULL(smu_sc, st->priv, SMU_SC_MAGIC);
 	if (warn)
 		return;
-	umem_cache_destroy(smu_sc->smu_cache);
+	umem_cache_destroyf(smu_sc->smu_cache);
 	smu_sc->smu_cache = NULL;
 
 	/*
diff --git a/configure.ac b/configure.ac
index db46168..3aeb7bb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -83,7 +83,7 @@ _VARNISH_CHECK_LIB(nsl, getaddrinfo)
 AC_SUBST(NET_LIBS, "${SOCKET_LIBS} ${NSL_LIBS}")
 
 # Userland slab allocator from Solaris, ported to other systems
-AC_CHECK_HEADERS([umem.h], [_VARNISH_CHECK_LIB(umem, umem_alloc)])
+AC_CHECK_HEADERS([umem.h])
 
 # XXX: This _may_ be for OS/X
 AC_CHECK_LIBM


More information about the varnish-commit mailing list