@@ -526,27 +526,30 @@ static kern_return_t profiler_segv_handler
526
526
}
527
527
#endif
528
528
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 )
530
531
{
531
532
jl_lock_profile ();
533
+ // workaround for old keymgr bugs
532
534
void * unused = NULL ;
533
535
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 )
535
538
_dyld_atfork_prepare ();
536
539
return keymgr_locked ;
537
540
}
538
541
539
- static void jl_unlock_profile_mach (int keymgr_locked )
542
+ static void jl_unlock_profile_mach (int dlsymlock , int keymgr_locked )
540
543
{
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 (); \
543
546
if (keymgr_locked )
544
547
_keymgr_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST );
545
548
jl_unlock_profile ();
546
549
}
547
550
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)
550
553
551
554
void * mach_profile_listener (void * arg )
552
555
{
@@ -564,7 +567,7 @@ void *mach_profile_listener(void *arg)
564
567
HANDLE_MACH_ERROR ("mach_msg" , ret );
565
568
// sample each thread, round-robin style in reverse order
566
569
// (so that thread zero gets notified last)
567
- jl_lock_profile ( );
570
+ int keymgr_locked = jl_lock_profile_mach ( 0 );
568
571
jl_shuffle_int_array_inplace (profile_round_robin_thread_order , jl_n_threads , & profile_cong_rng_seed );
569
572
for (int idx = jl_n_threads ; idx -- > 0 ; ) {
570
573
// Stop the threads in the random round-robin order.
@@ -575,9 +578,13 @@ void *mach_profile_listener(void *arg)
575
578
break ;
576
579
}
577
580
581
+ if (_dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
582
+ _dyld_atfork_prepare (); // briefly acquire the dlsym lock
578
583
host_thread_state_t state ;
579
584
jl_thread_suspend_and_get_state2 (i , & state );
580
585
unw_context_t * uc = (unw_context_t * )& state ;
586
+ if (_dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
587
+ _dyld_atfork_parent (); // quickly release the dlsym lock
581
588
582
589
if (running ) {
583
590
#ifdef LLVMLIBUNWIND
@@ -634,7 +641,7 @@ void *mach_profile_listener(void *arg)
634
641
// We're done! Resume the thread.
635
642
jl_thread_resume (i , 0 );
636
643
}
637
- jl_unlock_profile ( );
644
+ jl_unlock_profile_mach ( 0 , keymgr_locked );
638
645
if (running ) {
639
646
// Reset the alarm
640
647
kern_return_t ret = clock_alarm (clk , TIME_RELATIVE , timerprof , profile_port );
0 commit comments