Cleanup usage of malloc_usable_size. (#8554)

* Add better control of malloc_usable_size() usage.
* Use malloc_usable_size on alpine libc daily job.
* Add no-malloc-usable-size daily jobs.
* Fix zmalloc(0) when HAVE_MALLOC_SIZE is undefined.

In order to align with the jemalloc behavior, this should never return
NULL or OOM panic.
This commit is contained in:
Yossi Gottlieb 2021-02-25 09:24:41 +02:00 committed by GitHub
parent c6f0ea2c81
commit 3ea4c43add
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 5 deletions

View File

@ -48,6 +48,25 @@ jobs:
- name: cluster tests - name: cluster tests
run: ./runtest-cluster run: ./runtest-cluster
test-ubuntu-no-malloc-usable-size:
runs-on: ubuntu-latest
if: github.repository == 'redis/redis'
timeout-minutes: 14400
steps:
- uses: actions/checkout@v2
- name: make
run: make MALLOC=libc CFLAGS=-DNO_MALLOC_USABLE_SIZE
- name: test
run: |
sudo apt-get install tcl8.6
./runtest --accurate --verbose --dump-logs
- name: module api test
run: ./runtest-moduleapi --verbose
- name: sentinel tests
run: ./runtest-sentinel
- name: cluster tests
run: ./runtest-cluster
test-ubuntu-32bit: test-ubuntu-32bit:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository == 'redis/redis' if: github.repository == 'redis/redis'
@ -132,6 +151,22 @@ jobs:
- name: module api test - name: module api test
run: ./runtest-moduleapi --valgrind --no-latency --verbose --clients 1 run: ./runtest-moduleapi --valgrind --no-latency --verbose --clients 1
test-valgrind-no-malloc-usable-size:
runs-on: ubuntu-latest
if: github.repository == 'redis/redis'
timeout-minutes: 14400
steps:
- uses: actions/checkout@v2
- name: make
run: make valgrind CFLAGS="-DNO_MALLOC_USABLE_SIZE"
- name: test
run: |
sudo apt-get update
sudo apt-get install tcl8.6 valgrind -y
./runtest --valgrind --verbose --clients 1 --dump-logs
- name: module api test
run: ./runtest-moduleapi --valgrind --no-latency --verbose --clients 1
test-centos7-jemalloc: test-centos7-jemalloc:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository == 'redis/redis' if: github.repository == 'redis/redis'
@ -250,7 +285,7 @@ jobs:
- name: make - name: make
run: | run: |
apk add build-base apk add build-base
make REDIS_CFLAGS='-Werror' USE_JEMALLOC=no make REDIS_CFLAGS='-Werror' USE_JEMALLOC=no CFLAGS=-DUSE_MALLOC_USABLE_SIZE
- name: test - name: test
run: | run: |
apk add tcl procps apk add tcl procps

View File

@ -60,6 +60,11 @@ void zlibc_free(void *ptr) {
#define ASSERT_NO_SIZE_OVERFLOW(sz) assert((sz) + PREFIX_SIZE > (sz)) #define ASSERT_NO_SIZE_OVERFLOW(sz) assert((sz) + PREFIX_SIZE > (sz))
#endif #endif
/* When using the libc allocator, use a minimum allocation size to match the
* jemalloc behavior that doesn't return NULL in this case.
*/
#define MALLOC_MIN_SIZE(x) ((x) > 0 ? (x) : sizeof(long))
/* Explicitly override malloc/free etc when using tcmalloc. */ /* Explicitly override malloc/free etc when using tcmalloc. */
#if defined(USE_TCMALLOC) #if defined(USE_TCMALLOC)
#define malloc(size) tc_malloc(size) #define malloc(size) tc_malloc(size)
@ -93,7 +98,7 @@ static void (*zmalloc_oom_handler)(size_t) = zmalloc_default_oom;
* '*usable' is set to the usable size if non NULL. */ * '*usable' is set to the usable size if non NULL. */
void *ztrymalloc_usable(size_t size, size_t *usable) { void *ztrymalloc_usable(size_t size, size_t *usable) {
ASSERT_NO_SIZE_OVERFLOW(size); ASSERT_NO_SIZE_OVERFLOW(size);
void *ptr = malloc(size+PREFIX_SIZE); void *ptr = malloc(MALLOC_MIN_SIZE(size)+PREFIX_SIZE);
if (!ptr) return NULL; if (!ptr) return NULL;
#ifdef HAVE_MALLOC_SIZE #ifdef HAVE_MALLOC_SIZE
@ -153,7 +158,7 @@ void zfree_no_tcache(void *ptr) {
* '*usable' is set to the usable size if non NULL. */ * '*usable' is set to the usable size if non NULL. */
void *ztrycalloc_usable(size_t size, size_t *usable) { void *ztrycalloc_usable(size_t size, size_t *usable) {
ASSERT_NO_SIZE_OVERFLOW(size); ASSERT_NO_SIZE_OVERFLOW(size);
void *ptr = calloc(1, size+PREFIX_SIZE); void *ptr = calloc(1, MALLOC_MIN_SIZE(size)+PREFIX_SIZE);
if (ptr == NULL) return NULL; if (ptr == NULL) return NULL;
#ifdef HAVE_MALLOC_SIZE #ifdef HAVE_MALLOC_SIZE
@ -675,6 +680,7 @@ int zmalloc_test(int argc, char **argv) {
UNUSED(argc); UNUSED(argc);
UNUSED(argv); UNUSED(argv);
printf("Malloc prefix size: %d\n", (int) PREFIX_SIZE);
printf("Initial used memory: %zu\n", zmalloc_used_memory()); printf("Initial used memory: %zu\n", zmalloc_used_memory());
ptr = zmalloc(123); ptr = zmalloc(123);
printf("Allocated 123 bytes; used: %zu\n", zmalloc_used_memory()); printf("Allocated 123 bytes; used: %zu\n", zmalloc_used_memory());

View File

@ -62,11 +62,18 @@
#endif #endif
/* On native libc implementations, we should still do our best to provide a /* On native libc implementations, we should still do our best to provide a
* HAVE_MALLOC_SIZE capability. * HAVE_MALLOC_SIZE capability. This can be set explicitly as well:
*
* NO_MALLOC_USABLE_SIZE disables it on all platforms, even if they are
* known to support it.
* USE_MALLOC_USABLE_SIZE forces use of malloc_usable_size() regardless
* of platform.
*/ */
#ifndef ZMALLOC_LIB #ifndef ZMALLOC_LIB
#define ZMALLOC_LIB "libc" #define ZMALLOC_LIB "libc"
#if defined(__GLIBC__) || defined(__FreeBSD__) #if !defined(NO_MALLOC_USABLE_SIZE) && \
(defined(__GLIBC__) || defined(__FreeBSD__) || \
defined(USE_MALLOC_USABLE_SIZE))
#include <malloc.h> #include <malloc.h>
#define HAVE_MALLOC_SIZE 1 #define HAVE_MALLOC_SIZE 1
#define zmalloc_size(p) malloc_usable_size(p) #define zmalloc_size(p) malloc_usable_size(p)