@@ -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
{
@@ -565,17 +568,21 @@ void *mach_profile_listener(void *arg)
565
568
HANDLE_MACH_ERROR ("mach_msg" , ret );
566
569
// sample each thread, round-robin style in reverse order
567
570
// (so that thread zero gets notified last)
568
- jl_lock_profile ( );
571
+ int keymgr_locked = jl_lock_profile_mach ( 0 );
569
572
for (i = jl_n_threads ; i -- > 0 ; ) {
570
573
// if there is no space left, break early
571
574
if (jl_profile_is_buffer_full ()) {
572
575
jl_profile_stop_timer ();
573
576
break ;
574
577
}
575
578
579
+ if (_dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
580
+ _dyld_atfork_prepare (); // briefly acquire the dlsym lock
576
581
host_thread_state_t state ;
577
582
jl_thread_suspend_and_get_state2 (i , & state );
578
583
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
579
586
580
587
if (running ) {
581
588
#ifdef LLVMLIBUNWIND
@@ -618,7 +625,7 @@ void *mach_profile_listener(void *arg)
618
625
// We're done! Resume the thread.
619
626
jl_thread_resume (i , 0 );
620
627
}
621
- jl_unlock_profile ( );
628
+ jl_unlock_profile_mach ( 0 , keymgr_locked );
622
629
if (running ) {
623
630
// Reset the alarm
624
631
kern_return_t ret = clock_alarm (clk , TIME_RELATIVE , timerprof , profile_port );
0 commit comments