@@ -526,27 +526,30 @@ static kern_return_t profiler_segv_handler
526526}
527527#endif
528528
529- static int jl_lock_profile_mach (void )
529+ // WARNING: we are unable to handle sigsegv while the dlsymlock is held
530+ static int jl_lock_profile_mach (int dlsymlock )
530531{
531532 jl_lock_profile ();
533+ // workaround for old keymgr bugs
532534 void * unused = NULL ;
533535 int keymgr_locked = _keymgr_get_and_lock_processwide_ptr_2 (KEYMGR_GCC3_DW2_OBJ_LIST , & unused ) == 0 ;
534- if (_dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
536+ // workaround for new dlsym4 bugs (API and bugs introduced in macOS 12.1)
537+ if (dlsymlock && _dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
535538 _dyld_atfork_prepare ();
536539 return keymgr_locked ;
537540}
538541
539- static void jl_unlock_profile_mach (int keymgr_locked )
542+ static void jl_unlock_profile_mach (int dlsymlock , int keymgr_locked )
540543{
541- if (_dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
542- _dyld_atfork_parent ();
544+ if (dlsymlock && _dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL ) \
545+ _dyld_atfork_parent (); \
543546 if (keymgr_locked )
544547 _keymgr_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST );
545548 jl_unlock_profile ();
546549}
547550
548- #define jl_lock_profile () int keymgr_locked = jl_lock_profile_mach()
549- #define jl_unlock_profile () jl_unlock_profile_mach(keymgr_locked)
551+ #define jl_lock_profile () int keymgr_locked = jl_lock_profile_mach(1 )
552+ #define jl_unlock_profile () jl_unlock_profile_mach(1, keymgr_locked)
550553
551554void * mach_profile_listener (void * arg )
552555{
@@ -565,17 +568,21 @@ void *mach_profile_listener(void *arg)
565568 HANDLE_MACH_ERROR ("mach_msg" , ret );
566569 // sample each thread, round-robin style in reverse order
567570 // (so that thread zero gets notified last)
568- jl_lock_profile ( );
571+ int keymgr_locked = jl_lock_profile_mach ( 0 );
569572 for (i = jl_n_threads ; i -- > 0 ; ) {
570573 // if there is no space left, break early
571574 if (jl_profile_is_buffer_full ()) {
572575 jl_profile_stop_timer ();
573576 break ;
574577 }
575578
579+ if (_dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
580+ _dyld_atfork_prepare (); // briefly acquire the dlsym lock
576581 host_thread_state_t state ;
577582 jl_thread_suspend_and_get_state2 (i , & state );
578583 unw_context_t * uc = (unw_context_t * )& state ;
584+ if (_dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
585+ _dyld_atfork_parent (); // quickly release the dlsym lock
579586
580587 if (running ) {
581588#ifdef LLVMLIBUNWIND
@@ -618,7 +625,7 @@ void *mach_profile_listener(void *arg)
618625 // We're done! Resume the thread.
619626 jl_thread_resume (i , 0 );
620627 }
621- jl_unlock_profile ( );
628+ jl_unlock_profile_mach ( 0 , keymgr_locked );
622629 if (running ) {
623630 // Reset the alarm
624631 kern_return_t ret = clock_alarm (clk , TIME_RELATIVE , timerprof , profile_port );
0 commit comments