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()".
This commit is contained in:
Willy Tarreau 2021-09-15 10:05:48 +02:00
parent ea3323f62c
commit 157e393039
1 changed files with 25 additions and 0 deletions

View File

@ -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);