From d3068c3f4634bc7616d0e8896a4974daddb12b4a Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Mon, 9 Nov 2009 14:58:12 -0800 Subject: [PATCH] _pt_thread_death_internal(), which is part of Linux's nptl pthreads implementation, calls free() after calling TSD destructors. This was causing a crash during thread exit, since the magazine rack was no longer valid for the thread. Fix this by using a special mag_rack value to indicate that deallocation should bypass the magazine machinery. --- jemalloc/src/jemalloc.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/jemalloc/src/jemalloc.c b/jemalloc/src/jemalloc.c index c89ee117..410c0c45 100644 --- a/jemalloc/src/jemalloc.c +++ b/jemalloc/src/jemalloc.c @@ -3977,18 +3977,33 @@ arena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr) #ifdef JEMALLOC_MAG if (opt_mag) { mag_rack_t *rack = mag_rack; - if (rack == NULL) { - rack = mag_rack_create(arena); + if ((uintptr_t)rack > (uintptr_t)1) + mag_rack_dalloc(rack, ptr); + else { if (rack == NULL) { + rack = mag_rack_create(arena); + if (rack == NULL) { + malloc_spin_lock(&arena->lock); + arena_dalloc_small(arena, + chunk, ptr, mapelm); + malloc_spin_unlock( + &arena->lock); + } + mag_rack = rack; + pthread_setspecific(mag_rack_tsd, rack); + mag_rack_dalloc(rack, ptr); + } else { + /* + * This thread is currently exiting, so + * directly deallocate. + */ + assert(rack == (void *)(uintptr_t)1); malloc_spin_lock(&arena->lock); arena_dalloc_small(arena, chunk, ptr, mapelm); malloc_spin_unlock(&arena->lock); } - mag_rack = rack; - pthread_setspecific(mag_rack_tsd, rack); } - mag_rack_dalloc(rack, ptr); } else { #endif malloc_spin_lock(&arena->lock); @@ -5759,11 +5774,9 @@ thread_cleanup(void *arg) #ifdef JEMALLOC_MAG assert((mag_rack_t *)arg == mag_rack); if (mag_rack != NULL) { - assert(mag_rack != (void *)-1); + assert(mag_rack != (void *)(uintptr_t)1); mag_rack_destroy(mag_rack); -#ifdef JEMALLOC_DEBUG - mag_rack = (void *)-1; -#endif + mag_rack = (void *)(uintptr_t)1; } #endif }