Skip to content

Commit 9f70ce5

Browse files
committed
avoid accessing heap->tld after running thread_done (pr #974)
1 parent e183384 commit 9f70ce5

File tree

3 files changed

+13
-7
lines changed

3 files changed

+13
-7
lines changed

include/mimalloc/internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ void _mi_heap_destroy_pages(mi_heap_t* heap);
216216
void _mi_heap_collect_abandon(mi_heap_t* heap);
217217
void _mi_heap_set_default_direct(mi_heap_t* heap);
218218
bool _mi_heap_memid_is_suitable(mi_heap_t* heap, mi_memid_t memid);
219-
void _mi_heap_unsafe_destroy_all(void);
219+
void _mi_heap_unsafe_destroy_all(mi_heap_t* heap);
220220
mi_heap_t* _mi_heap_by_tag(mi_heap_t* heap, uint8_t tag);
221221
void _mi_heap_area_init(mi_heap_area_t* area, mi_page_t* page);
222222
bool _mi_heap_area_visit_blocks(const mi_heap_area_t* area, mi_page_t* page, mi_block_visit_fun* visitor, void* arg);

src/heap.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -393,9 +393,10 @@ void mi_heap_destroy(mi_heap_t* heap) {
393393
}
394394

395395
// forcefully destroy all heaps in the current thread
396-
void _mi_heap_unsafe_destroy_all(void) {
397-
mi_heap_t* bheap = mi_heap_get_backing();
398-
mi_heap_t* curr = bheap->tld->heaps;
396+
void _mi_heap_unsafe_destroy_all(mi_heap_t* heap) {
397+
mi_assert_internal(heap != NULL);
398+
if (heap == NULL) return;
399+
mi_heap_t* curr = heap->tld->heaps;
399400
while (curr != NULL) {
400401
mi_heap_t* next = curr->next;
401402
if (curr->no_reclaim) {

src/init.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -663,24 +663,29 @@ void mi_cdecl _mi_process_done(void) {
663663
if (process_done) return;
664664
process_done = true;
665665

666+
// get the default heap so we don't need to acces thread locals anymore
667+
mi_heap_t* heap = mi_prim_get_default_heap(); // use prim to not initialize any heap
668+
mi_assert_internal(heap != NULL);
669+
666670
// release any thread specific resources and ensure _mi_thread_done is called on all but the main thread
667671
_mi_prim_thread_done_auto_done();
668672

673+
669674
#ifndef MI_SKIP_COLLECT_ON_EXIT
670675
#if (MI_DEBUG || !defined(MI_SHARED_LIB))
671676
// free all memory if possible on process exit. This is not needed for a stand-alone process
672677
// but should be done if mimalloc is statically linked into another shared library which
673678
// is repeatedly loaded/unloaded, see issue #281.
674-
mi_collect(true /* force */ );
679+
mi_heap_collect(heap, true /* force */ );
675680
#endif
676681
#endif
677682

678683
// Forcefully release all retained memory; this can be dangerous in general if overriding regular malloc/free
679684
// since after process_done there might still be other code running that calls `free` (like at_exit routines,
680685
// or C-runtime termination code.
681686
if (mi_option_is_enabled(mi_option_destroy_on_exit)) {
682-
mi_collect(true /* force */);
683-
_mi_heap_unsafe_destroy_all(); // forcefully release all memory held by all heaps (of this thread only!)
687+
mi_heap_collect(heap, true /* force */);
688+
_mi_heap_unsafe_destroy_all(heap); // forcefully release all memory held by all heaps (of this thread only!)
684689
_mi_arena_unsafe_destroy_all();
685690
_mi_segment_map_unsafe_destroy();
686691
}

0 commit comments

Comments
 (0)