Skip to content

Set _mi_process_is_initialized before mi_process_setup_auto_thread_done (fixes 439dc27b with MI_TLS_RECURSE_GUARD) - #1399

Open
LongYinan (Brooooooklyn) wants to merge 1 commit into
microsoft:dev3from
napi-rs:fix/process-init-flag-before-thread-done
Open

Set _mi_process_is_initialized before mi_process_setup_auto_thread_done (fixes 439dc27b with MI_TLS_RECURSE_GUARD)#1399
LongYinan (Brooooooklyn) wants to merge 1 commit into
microsoft:dev3from
napi-rs:fix/process-init-flag-before-thread-done

Conversation

@Brooooooklyn

Copy link
Copy Markdown
Contributor

Follow-up to #1393 / 439dc27. Thanks for taking that fix; it works on the default TLS model (the #1393 repro passes on v3.5.2 on Linux). It regresses with MI_TLS_RECURSE_GUARD though, which is always on for MI_TLS_MODEL_LOCAL on macOS (prim-tls.h):

#if !defined(MI_TLS_RECURSE_GUARD) && MI_TLS_MODEL_LOCAL && defined(__APPLE__)
#define MI_TLS_RECURSE_GUARD 1
#endif

439dc27 moved mi_process_setup_auto_thread_done() into mi_process_init_once() so it runs after mi_thread_init(), but it now runs before _mi_process_is_initialized = true. With the guard, _mi_theap_default() returns _mi_theap_empty until that flag is set:

mi_process_init_once()
  mi_thread_init()                       __mi_theap_default = &mi_process_theap_main
  _mi_tls_slots_init()
  _mi_thread_locals_init()
  mi_process_setup_auto_thread_done()
    _mi_theap_default()                  -> guard: !_mi_process_is_initialized -> &_mi_theap_empty
    mi_assert_internal(mi_theap_is_initialized(theap))   -> fires in debug
    if (mi_theap_is_initialized(theap)) ...              -> skipped in release
  _mi_process_is_initialized = true      <- too late

So in debug builds every process aborts at init:

mimalloc: assertion failed: at "src/init.c":450, mi_process_setup_auto_thread_done
  assertion: "mi_theap_is_initialized(theap)"

and in release builds the first thread's theap is again never associated with the thread-done key, i.e. the #1393 leak is back for that configuration.

Repro (macOS arm64, v3.5.2):

cmake -B build -DCMAKE_BUILD_TYPE=Debug -DMI_TLS_MODEL=LOCAL
cmake --build build
./build/mimalloc-test-api      # aborts; v3.5.1 passes 50/50

Same on Linux with -DMI_TLS_RECURSE_GUARD=ON (the #1393 repro aborts; with this patch it prints OK).

Fix: set _mi_process_is_initialized = true before mi_process_setup_auto_thread_done(). The theap is fully initialized by then (mi_thread_init() asserts that), and the pthread key creation inside can allocate through it if it needs to.

Verified:

macOS, Debug, -DMI_TLS_MODEL=LOCAL, mimalloc-test-api
v3.5.1 50/50
v3.5.2 abort
v3.5.2 + this 50/50
Linux x64, Debug shared, #1393 repro guard OFF guard ON
v3.5.2 OK abort
v3.5.2 + this OK OK

mimalloc-test-stress-heaps fails the refcount == 1 assert in mi_thread_theaps_done with -DMI_TLS_MODEL=LOCAL on macOS, but it does so on v3.5.1 too, so that is unrelated to this change.

439dc27 moved `mi_process_setup_auto_thread_done` into
`mi_process_init_once` so it runs after `mi_thread_init` and can
associate the current theap with the thread-done key. It now runs
before `_mi_process_is_initialized = true`, and with
`MI_TLS_RECURSE_GUARD` (always on for `MI_TLS_MODEL_LOCAL` on macOS)
`_mi_theap_default()` still returns `_mi_theap_empty` at that point.
The new `mi_assert_internal(mi_theap_is_initialized(theap))` fires in
debug builds; release builds skip the association, so the first
thread's theap is again never passed to `_mi_thread_done`.

Repro (macOS): `cmake -DCMAKE_BUILD_TYPE=Debug -DMI_TLS_MODEL=LOCAL`
then `./mimalloc-test-api` aborts at process init on v3.5.2 and
passes on v3.5.1. Same with `-DMI_TLS_RECURSE_GUARD=ON` on Linux.

Set the flag before `mi_process_setup_auto_thread_done`; the theap is
fully initialized by then.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016srh5svTkqfW21zGcU6ht9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant