From 157e393039966fa9a1b4f9a5ca964ec56f28204b Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 15 Sep 2021 10:05:48 +0200 Subject: [PATCH] MINOR: pools: automatically disable malloc_trim() with external allocators Pierre Cheynier reported some occasional crashes in malloc_trim() on a recent glibc when running with jemalloc(). While in theory there should not be any link between the two, it remains plausible that something allocated early with one is tentatively freed with the other and that attempts to trim end up badly. There's no point calling the glibc specific malloc_trim() with external allocators anyway. However these ones are often enabled at link time or even at run time with LD_PRELOAD, so we cannot rely on build options for this. This patch implements runtime detection for the allocator in use by checking with mallinfo() that a malloc() call is properly accounted for in glibc's malloc. It only enables malloc_trim() in this case, and ignores it for other cases. It's fine to proceed like this because mallinfo() is provided by a wider range of glibcs than malloc_trim(). This could be backported to 2.4 and 2.3. If so, it will also need previous patch "CLEANUP: pools: factor all malloc_trim() calls into trim_all_pools()". --- src/pool.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/pool.c b/src/pool.c index 60f21d6773..f1c165d631 100644 --- a/src/pool.c +++ b/src/pool.c @@ -41,6 +41,8 @@ static int mem_fail_rate = 0; #endif #if defined(HA_HAVE_MALLOC_TRIM) +static int using_libc_allocator = 0; + /* ask the allocator to trim memory pools */ static void trim_all_pools(void) { @@ -48,11 +50,33 @@ static void trim_all_pools(void) malloc_trim(0); } +/* check if we're using the same allocator as the one that provides + * malloc_trim() and mallinfo(). The principle is that on glibc, both + * malloc_trim() and mallinfo() are provided, and using mallinfo() we + * can check if malloc() is performed through glibc or any other one + * the executable was linked against (e.g. jemalloc). + */ +static void detect_allocator(void) +{ + struct mallinfo mi1, mi2; + void *ptr; + + mi1 = mallinfo(); + ptr = DISGUISE(malloc(1)); + mi2 = mallinfo(); + free(DISGUISE(ptr)); + + using_libc_allocator = !!memcmp(&mi1, &mi2, sizeof(mi1)); +} #else static void trim_all_pools(void) { } + +static void detect_allocator(void) +{ +} #endif /* Try to find an existing shared pool with the same characteristics and @@ -511,6 +535,7 @@ static void init_pools() LIST_INIT(&ha_thread_info[thr].pool_lru_head); } #endif + detect_allocator(); } INITCALL0(STG_PREPARE, init_pools); -- 2.39.5