@@ -257,22 +257,37 @@ static _Atomic(size_t) warning_count; // = 0; // when >= max_warning_count stop
257257
258258// When overriding malloc, we may recurse into mi_vfprintf if an allocation
259259// inside the C runtime causes another message.
260+ // In some cases (like on macOS) the loader already allocates which
261+ // calls into mimalloc; if we then access thread locals (like `recurse`)
262+ // this may crash as the access may call _tlv_bootstrap that tries to
263+ // (recursively) invoke malloc again to allocate space for the thread local
264+ // variables on demand. This is why we use a _mi_preloading test on such
265+ // platforms. However, code gen may move the initial thread local address
266+ // load before the `if` and we therefore split it out in a separate funcion.
260267static mi_decl_thread bool recurse = false;
261268
269+ static mi_decl_noinline bool mi_recurse_enter_prim (void ) {
270+ if (recurse ) return false;
271+ recurse = true;
272+ return true;
273+ }
274+
275+ static mi_decl_noinline void mi_recurse_exit_prim (void ) {
276+ recurse = false;
277+ }
278+
262279static bool mi_recurse_enter (void ) {
263280 #if defined(__APPLE__ ) || defined(MI_TLS_RECURSE_GUARD )
264281 if (_mi_preloading ()) return true;
265282 #endif
266- if (recurse ) return false;
267- recurse = true;
268- return true;
283+ return mi_recurse_enter_prim ();
269284}
270285
271286static void mi_recurse_exit (void ) {
272287 #if defined(__APPLE__ ) || defined(MI_TLS_RECURSE_GUARD )
273288 if (_mi_preloading ()) return ;
274289 #endif
275- recurse = false ;
290+ mi_recurse_exit_prim () ;
276291}
277292
278293void _mi_fputs (mi_output_fun * out , void * arg , const char * prefix , const char * message ) {
0 commit comments