Do not include libc_common in malloc debug code.
The inclusion of the static libc_common library in the malloc_debug_XXX.so
shared libraries causes constructors to be called twice. This doesn't seem
to have caused any issues when setting the libc.debug.malloc property.
However, jemalloc crashes because there are two jemalloc implementations,
one in the static libc_common library and one in the shared library. Each
implementation has created overlapping thread keys that are not the same.
The crash comes because one of the jemalloc keys is actually used by the
locale setting code. Thus if someone sets the locale, the jemalloc code
crashes trying to access the same key.
Change-Id: Iaac650a82d69064db148a6333e9403744f68b4a4
diff --git a/libc/bionic/malloc_debug_check.cpp b/libc/bionic/malloc_debug_check.cpp
index e4e4c2e..1b6f8ea 100644
--- a/libc/bionic/malloc_debug_check.cpp
+++ b/libc/bionic/malloc_debug_check.cpp
@@ -123,6 +123,7 @@
static unsigned g_malloc_debug_backlog = 100;
__LIBC_HIDDEN__ HashTable* g_hash_table;
+__LIBC_HIDDEN__ const MallocDebug* g_malloc_dispatch;
static inline void init_front_guard(hdr_t* hdr) {
memset(hdr->front_guard, FRONT_GUARD, FRONT_GUARD_LEN);
@@ -324,7 +325,7 @@
while (backlog_num > g_malloc_debug_backlog) {
hdr_t* gone = backlog_tail;
del_from_backlog_locked(gone);
- Malloc(free)(gone->base);
+ g_malloc_dispatch->free(gone->base);
}
}
@@ -336,7 +337,7 @@
errno = ENOMEM;
return NULL;
}
- hdr_t* hdr = static_cast<hdr_t*>(Malloc(malloc)(size));
+ hdr_t* hdr = static_cast<hdr_t*>(g_malloc_dispatch->malloc(size));
if (hdr) {
hdr->base = hdr;
hdr->bt_depth = get_backtrace(hdr->bt, MAX_BACKTRACE_DEPTH);
@@ -364,7 +365,7 @@
return NULL;
}
- void* base = Malloc(malloc)(sizeof(hdr_t) + size + sizeof(ftr_t));
+ void* base = g_malloc_dispatch->malloc(sizeof(hdr_t) + size + sizeof(ftr_t));
if (base != NULL) {
// Check that the actual pointer that will be returned is aligned
// properly.
@@ -461,7 +462,7 @@
user(hdr), bytes);
log_backtrace(bt, depth);
// just get a whole new allocation and leak the old one
- return Malloc(realloc)(0, bytes);
+ return g_malloc_dispatch->realloc(0, bytes);
// return realloc(user(hdr), bytes); // assuming it was allocated externally
}
}
@@ -474,15 +475,15 @@
if (hdr->base != hdr) {
// An allocation from memalign, so create another allocation and
// copy the data out.
- void* newMem = Malloc(malloc)(size);
+ void* newMem = g_malloc_dispatch->malloc(size);
if (newMem == NULL) {
return NULL;
}
memcpy(newMem, hdr, sizeof(hdr_t) + hdr->size);
- Malloc(free)(hdr->base);
+ g_malloc_dispatch->free(hdr->base);
hdr = static_cast<hdr_t*>(newMem);
} else {
- hdr = static_cast<hdr_t*>(Malloc(realloc)(hdr, size));
+ hdr = static_cast<hdr_t*>(g_malloc_dispatch->realloc(hdr, size));
}
if (hdr) {
hdr->base = hdr;
@@ -501,7 +502,7 @@
errno = ENOMEM;
return NULL;
}
- hdr_t* hdr = static_cast<hdr_t*>(Malloc(calloc)(1, size));
+ hdr_t* hdr = static_cast<hdr_t*>(g_malloc_dispatch->calloc(1, size));
if (hdr) {
hdr->base = hdr;
hdr->bt_depth = get_backtrace(hdr->bt, MAX_BACKTRACE_DEPTH);
@@ -524,7 +525,7 @@
}
extern "C" struct mallinfo chk_mallinfo() {
- return Malloc(mallinfo)();
+ return g_malloc_dispatch->mallinfo();
}
extern "C" int chk_posix_memalign(void** memptr, size_t alignment, size_t size) {
@@ -584,8 +585,9 @@
}
}
-extern "C" bool malloc_debug_initialize(HashTable* hash_table) {
+extern "C" bool malloc_debug_initialize(HashTable* hash_table, const MallocDebug* malloc_dispatch) {
g_hash_table = hash_table;
+ g_malloc_dispatch = malloc_dispatch;
char debug_backlog[PROP_VALUE_MAX];
if (__system_property_get("libc.debug.malloc.backlog", debug_backlog)) {