From d936b46d3a6320895ddd9a16dc4c5e79d5b9d8e9 Mon Sep 17 00:00:00 2001 From: "David T. Goldblatt" Date: Sun, 29 Mar 2020 10:41:23 -0700 Subject: [PATCH] Add malloc_conf_2_conf_harder This comes in handy when you're just a user of a canary system who wants to change settings set by the configuration system itself. --- Makefile.in | 1 + configure.ac | 3 ++- src/jemalloc.c | 35 ++++++++++++++++++++++++++++++++--- test/unit/malloc_conf_2.c | 29 +++++++++++++++++++++++++++++ test/unit/malloc_conf_2.sh | 1 + 5 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 test/unit/malloc_conf_2.c create mode 100644 test/unit/malloc_conf_2.sh diff --git a/Makefile.in b/Makefile.in index 7300cb98..10af489b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -209,6 +209,7 @@ TESTS_UNIT := \ $(srcroot)test/unit/junk_free.c \ $(srcroot)test/unit/log.c \ $(srcroot)test/unit/mallctl.c \ + $(srcroot)test/unit/malloc_conf_2.c \ $(srcroot)test/unit/malloc_io.c \ $(srcroot)test/unit/math.c \ $(srcroot)test/unit/mq.c \ diff --git a/configure.ac b/configure.ac index 324656b9..daac2050 100644 --- a/configure.ac +++ b/configure.ac @@ -1000,7 +1000,8 @@ AC_ARG_WITH([export], fi] ) -public_syms="aligned_alloc calloc dallocx free mallctl mallctlbymib mallctlnametomib malloc malloc_conf malloc_message malloc_stats_print malloc_usable_size mallocx smallocx_${jemalloc_version_gid} nallocx posix_memalign rallocx realloc sallocx sdallocx xallocx" +public_syms="aligned_alloc calloc dallocx free mallctl mallctlbymib +mallctlnametomib malloc malloc_conf malloc_conf_2_conf_harder malloc_message malloc_stats_print malloc_usable_size mallocx smallocx_${jemalloc_version_gid} nallocx posix_memalign rallocx realloc sallocx sdallocx xallocx" dnl Check for additional platform-specific public API functions. AC_CHECK_FUNC([memalign], [AC_DEFINE([JEMALLOC_OVERRIDE_MEMALIGN], [ ]) diff --git a/src/jemalloc.c b/src/jemalloc.c index ea331f82..63f7ebfa 100644 --- a/src/jemalloc.c +++ b/src/jemalloc.c @@ -32,6 +32,29 @@ const char *je_malloc_conf JEMALLOC_ATTR(weak) #endif ; +/* + * The usual rule is that the closer to runtime you are, the higher priority + * your configuration settings are (so the jemalloc config options get lower + * priority than the per-binary setting, which gets lower priority than the /etc + * setting, which gets lower priority than the environment settings). + * + * But it's a fairly common use case in some testing environments for a user to + * be able to control the binary, but nothing else (e.g. a performancy canary + * uses the production OS and environment variables, but can run any binary in + * those circumstances). For these use cases, it's handy to have an in-binary + * mechanism for overriding environment variable settings, with the idea that if + * the results are positive they get promoted to the official settings, and + * moved from the binary to the environment variable. + * + * We don't actually want this to be widespread, so we'll give it a silly name + * and not mention it in headers or documentation. + */ +const char *je_malloc_conf_2_conf_harder +#ifndef _WIN32 + JEMALLOC_ATTR(weak) +#endif + ; + bool opt_abort = #ifdef JEMALLOC_DEBUG true @@ -975,7 +998,7 @@ malloc_slow_flag_init(void) { } /* Number of sources for initializing malloc_conf */ -#define MALLOC_CONF_NSOURCES 4 +#define MALLOC_CONF_NSOURCES 5 static const char * obtain_malloc_conf(unsigned which_source, char buf[PATH_MAX + 1]) { @@ -1053,6 +1076,9 @@ obtain_malloc_conf(unsigned which_source, char buf[PATH_MAX + 1]) { ret = NULL; } break; + } case 4: { + ret = je_malloc_conf_2_conf_harder; + break; } default: not_reached(); ret = NULL; @@ -1069,7 +1095,9 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], "string pointed to by the global variable malloc_conf", "\"name\" of the file referenced by the symbolic link named " "/etc/malloc.conf", - "value of the environment variable MALLOC_CONF" + "value of the environment variable MALLOC_CONF", + "string pointed to by the global variable " + "malloc_conf_2_conf_harder", }; unsigned i; const char *opts, *k, *v; @@ -1506,7 +1534,8 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS], static void malloc_conf_init(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS]) { - const char *opts_cache[MALLOC_CONF_NSOURCES] = {NULL, NULL, NULL, NULL}; + const char *opts_cache[MALLOC_CONF_NSOURCES] = {NULL, NULL, NULL, NULL, + NULL}; char buf[PATH_MAX + 1]; /* The first call only set the confirm_conf option and opts_cache */ diff --git a/test/unit/malloc_conf_2.c b/test/unit/malloc_conf_2.c new file mode 100644 index 00000000..ecfa4991 --- /dev/null +++ b/test/unit/malloc_conf_2.c @@ -0,0 +1,29 @@ +#include "test/jemalloc_test.h" + +const char *malloc_conf = "dirty_decay_ms:1000"; +const char *malloc_conf_2_conf_harder = "dirty_decay_ms:1234"; + +TEST_BEGIN(test_malloc_conf_2) { +#ifdef _WIN32 + bool windows = true; +#else + bool windows = false; +#endif + /* Windows doesn't support weak symbol linker trickery. */ + test_skip_if(windows); + + ssize_t dirty_decay_ms; + size_t sz = sizeof(dirty_decay_ms); + + int err = mallctl("opt.dirty_decay_ms", &dirty_decay_ms, &sz, NULL, 0); + assert_d_eq(err, 0, "Unexpected mallctl failure"); + expect_zd_eq(dirty_decay_ms, 1234, + "malloc_conf_2 setting didn't take effect"); +} +TEST_END + +int +main(void) { + return test( + test_malloc_conf_2); +} diff --git a/test/unit/malloc_conf_2.sh b/test/unit/malloc_conf_2.sh new file mode 100644 index 00000000..2c780f1a --- /dev/null +++ b/test/unit/malloc_conf_2.sh @@ -0,0 +1 @@ +export MALLOC_CONF="dirty_decay_ms:500"