@@ -516,27 +516,30 @@ static kern_return_t profiler_segv_handler
516516}
517517#endif
518518
519- static int jl_lock_profile_mach (void )
519+ // WARNING: we are unable to handle sigsegv while the dlsymlock is held
520+ static int jl_lock_profile_mach (int dlsymlock )
520521{
521522 jl_lock_profile ();
523+ // workaround for old keymgr bugs
522524 void * unused = NULL ;
523525 int keymgr_locked = _keymgr_get_and_lock_processwide_ptr_2 (KEYMGR_GCC3_DW2_OBJ_LIST , & unused ) == 0 ;
524- if (_dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
526+ // workaround for new dlsym4 bugs (API and bugs introduced in macOS 12.1)
527+ if (dlsymlock && _dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
525528 _dyld_atfork_prepare ();
526529 return keymgr_locked ;
527530}
528531
529- static void jl_unlock_profile_mach (int keymgr_locked )
532+ static void jl_unlock_profile_mach (int dlsymlock , int keymgr_locked )
530533{
531- if (_dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
532- _dyld_atfork_parent ();
534+ if (dlsymlock && _dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL ) \
535+ _dyld_atfork_parent (); \
533536 if (keymgr_locked )
534537 _keymgr_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST );
535538 jl_unlock_profile ();
536539}
537540
538- #define jl_lock_profile () int keymgr_locked = jl_lock_profile_mach()
539- #define jl_unlock_profile () jl_unlock_profile_mach(keymgr_locked)
541+ #define jl_lock_profile () int keymgr_locked = jl_lock_profile_mach(1 )
542+ #define jl_unlock_profile () jl_unlock_profile_mach(1, keymgr_locked)
540543
541544void * mach_profile_listener (void * arg )
542545{
@@ -555,17 +558,21 @@ void *mach_profile_listener(void *arg)
555558 HANDLE_MACH_ERROR ("mach_msg" , ret );
556559 // sample each thread, round-robin style in reverse order
557560 // (so that thread zero gets notified last)
558- jl_lock_profile ( );
561+ int keymgr_locked = jl_lock_profile_mach ( 0 );
559562 for (i = jl_n_threads ; i -- > 0 ; ) {
560563 // if there is no space left, break early
561564 if (jl_profile_is_buffer_full ()) {
562565 jl_profile_stop_timer ();
563566 break ;
564567 }
565568
569+ if (_dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
570+ _dyld_atfork_prepare (); // briefly acquire the dlsym lock
566571 host_thread_state_t state ;
567572 jl_thread_suspend_and_get_state2 (i , & state );
568573 unw_context_t * uc = (unw_context_t * )& state ;
574+ if (_dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
575+ _dyld_atfork_parent (); // quickly release the dlsym lock
569576
570577 if (running ) {
571578#ifdef LIBOSXUNWIND
@@ -608,7 +615,7 @@ void *mach_profile_listener(void *arg)
608615 // We're done! Resume the thread.
609616 jl_thread_resume (i , 0 );
610617 }
611- jl_unlock_profile ( );
618+ jl_unlock_profile_mach ( 0 , keymgr_locked );
612619 if (running ) {
613620 // Reset the alarm
614621 kern_return_t ret = clock_alarm (clk , TIME_RELATIVE , timerprof , profile_port );
0 commit comments