Associate the process-init thread's theap with the thread-done key - #1393
Open
LongYinan (Brooooooklyn) wants to merge 1 commit into
Open
Associate the process-init thread's theap with the thread-done key#1393LongYinan (Brooooooklyn) wants to merge 1 commit into
LongYinan (Brooooooklyn) wants to merge 1 commit into
Conversation
The thread that runs `mi_process_init` initializes its default theap before `mi_process_setup_auto_thread_done` creates the pthread thread-done key, so `_mi_prim_thread_associate_default_theap` is a no-op for it and `_mi_thread_done` never runs when that thread terminates. Up to v3.4.5, `mi_process_setup_auto_thread_done` re-associated it right after creating the key (`_mi_theap_default_set(&mi_process_theap_main)`); 5d9cb38 ("remove static main theap and tld") dropped that call, so since v3.5.0 nothing associates the first thread. When the first thread to touch mimalloc is short-lived (for example a Node.js worker thread that dlopen's an addon statically linked with mimalloc, then exits), its theap stays registered in the heap with its thread id. A later thread that reuses the same pthread TCB finds it in `mi_heap_check_for_existing_theap` and trips `mi_assert_internal(theap==NULL)` in `_mi_thread_init_with_heap` in debug builds; release builds skip the check but the dead thread's theap and pages are never abandoned or freed. Associate the current default theap with the key right after creating it, when it is already initialized. The v2 line (dev) still does the equivalent via `_mi_heap_set_default_direct(&_mi_heap_main)`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T34fMrYCf2V13Mg8BKmnda
LongYinan (Brooooooklyn)
added a commit
to napi-rs/mimalloc-safe
that referenced
this pull request
Sep 4, 2026
…-done hook (#97) mimalloc v3.5.0 never associates the process-init thread's theap with the pthread thread-done key; when that first thread exits (a Node.js worker that loads the addon first), the next thread that reuses its pthread TCB aborts in debug builds (init.c "theap==NULL") and release builds leak the dead thread's theap and pages. Point the mimalloc3 submodule at napi-rs/mimalloc:fix/first-thread-done = upstream v3.5.1 + the fix (microsoft/mimalloc#1393). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T34fMrYCf2V13Mg8BKmnda
LongYinan (Brooooooklyn)
added a commit
to rolldown/rolldown
that referenced
this pull request
Sep 4, 2026
0.1.66 ships mimalloc v3.5.1 plus the fix for the process-init thread's thread-done hook (see microsoft/mimalloc#1393, napi-rs/mimalloc-safe#97), so the `=0.1.64` stopgap from 4855394 is no longer needed. Cargo.lock: mimalloc-safe 0.1.64 -> 0.1.66, libmimalloc-sys2 0.1.60 -> 0.1.62. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T34fMrYCf2V13Mg8BKmnda
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Since v3.5.0 the thread that runs
mi_process_initnever gets its theap associated with the thread-done key._mi_thread_init_with_heapruns beforemi_process_setup_auto_thread_donecreates the key, so_mi_prim_thread_associate_default_theapis a no-op for that thread, and the call that used to fix this up afterwards (_mi_theap_default_set(&mi_process_theap_main)) was removed in 5d9cb38 ("remove static main theap and tld"). If that first thread exits,_mi_thread_donenever runs for it and its theap stays registered with its thread id.We hit this with a Node.js addon that links mimalloc statically: a worker thread loads the addon first (so the constructor runs there), exits, and the next thread that gets the same pthread TCB aborts on its first allocation in debug builds:
Release builds skip the assert and just leak the dead thread's theap and pages. v3.4.5 is fine, v3.5.1 still has it. The v2 line does the equivalent association in
_mi_heap_set_default_direct(&_mi_heap_main).The fix associates the current theap with the key right after creating it, if it is already initialized. Teardown of the static main theap already works once the destructor fires (
_mi_tld_detach_theaps, static memid skipped,thread_idset toMI_THREADID_INVALID).ctestpasses before and after; the existing tests never let the first thread exit, so they don't catch this.Standalone repro (mimalloc built with
-DCMAKE_BUILD_TYPE=Debug -DMI_BUILD_SHARED=ON)Before: T1 and T2 print the same
pthread_self, then the assertion above. After:OK.