Skip to content

Commit

Permalink
avoid accessing heap->tld after running thread_done (pr #974)
Browse files Browse the repository at this point in the history
  • Loading branch information
daanx committed Dec 30, 2024
1 parent e183384 commit 9f70ce5
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 7 deletions.
2 changes: 1 addition & 1 deletion include/mimalloc/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ void _mi_heap_destroy_pages(mi_heap_t* heap);
void _mi_heap_collect_abandon(mi_heap_t* heap);
void _mi_heap_set_default_direct(mi_heap_t* heap);
bool _mi_heap_memid_is_suitable(mi_heap_t* heap, mi_memid_t memid);
void _mi_heap_unsafe_destroy_all(void);
void _mi_heap_unsafe_destroy_all(mi_heap_t* heap);
mi_heap_t* _mi_heap_by_tag(mi_heap_t* heap, uint8_t tag);
void _mi_heap_area_init(mi_heap_area_t* area, mi_page_t* page);
bool _mi_heap_area_visit_blocks(const mi_heap_area_t* area, mi_page_t* page, mi_block_visit_fun* visitor, void* arg);
Expand Down
7 changes: 4 additions & 3 deletions src/heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,9 +393,10 @@ void mi_heap_destroy(mi_heap_t* heap) {
}

// forcefully destroy all heaps in the current thread
void _mi_heap_unsafe_destroy_all(void) {
mi_heap_t* bheap = mi_heap_get_backing();
mi_heap_t* curr = bheap->tld->heaps;
void _mi_heap_unsafe_destroy_all(mi_heap_t* heap) {
mi_assert_internal(heap != NULL);
if (heap == NULL) return;
mi_heap_t* curr = heap->tld->heaps;
while (curr != NULL) {
mi_heap_t* next = curr->next;
if (curr->no_reclaim) {
Expand Down
11 changes: 8 additions & 3 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -663,24 +663,29 @@ void mi_cdecl _mi_process_done(void) {
if (process_done) return;
process_done = true;

// get the default heap so we don't need to acces thread locals anymore
mi_heap_t* heap = mi_prim_get_default_heap(); // use prim to not initialize any heap
mi_assert_internal(heap != NULL);

// release any thread specific resources and ensure _mi_thread_done is called on all but the main thread
_mi_prim_thread_done_auto_done();


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

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

0 comments on commit 9f70ce5

Please sign in to comment.