@@ -36,6 +36,9 @@ extern int _keymgr_set_lockmode_processwide_ptr(unsigned int key, unsigned int m
36
36
extern void _dyld_atfork_prepare (void ) __attribute__((weak_import ));
37
37
extern void _dyld_atfork_parent (void ) __attribute__((weak_import ));
38
38
//extern void _dyld_fork_child(void) __attribute__((weak_import));
39
+ extern void _dyld_dlopen_atfork_prepare (void ) __attribute__((weak_import ));
40
+ extern void _dyld_dlopen_atfork_parent (void ) __attribute__((weak_import ));
41
+ //extern void _dyld_dlopen_atfork_child(void) __attribute__((weak_import));
39
42
40
43
static void attach_exception_port (thread_port_t thread , int segv_only );
41
44
@@ -568,16 +571,23 @@ static int jl_lock_profile_mach(int dlsymlock)
568
571
// workaround for old keymgr bugs
569
572
void * unused = NULL ;
570
573
int keymgr_locked = _keymgr_get_and_lock_processwide_ptr_2 (KEYMGR_GCC3_DW2_OBJ_LIST , & unused ) == 0 ;
571
- // workaround for new dlsym4 bugs (API and bugs introduced in macOS 12.1)
574
+ // workaround for new dlsym4 bugs in the workaround for dlsym bugs: _dyld_atfork_prepare
575
+ // acquires its locks in the wrong order, but fortunately we happen to able to guard it
576
+ // with this call to force it to prevent that TSAN violation from causing a deadlock
577
+ if (dlsymlock && _dyld_dlopen_atfork_prepare != NULL && _dyld_dlopen_atfork_parent != NULL )
578
+ _dyld_dlopen_atfork_prepare ();
579
+ // workaround for new dlsym4 bugs (API and bugs introduced circa macOS 12.1)
572
580
if (dlsymlock && _dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
573
581
_dyld_atfork_prepare ();
574
582
return keymgr_locked ;
575
583
}
576
584
577
585
static void jl_unlock_profile_mach (int dlsymlock , int keymgr_locked )
578
586
{
579
- if (dlsymlock && _dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL ) \
580
- _dyld_atfork_parent (); \
587
+ if (dlsymlock && _dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
588
+ _dyld_atfork_parent ();
589
+ if (dlsymlock && _dyld_dlopen_atfork_prepare != NULL && _dyld_dlopen_atfork_parent != NULL )
590
+ _dyld_dlopen_atfork_parent ();
581
591
if (keymgr_locked )
582
592
_keymgr_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST );
583
593
jl_unlock_profile ();
@@ -622,14 +632,19 @@ void *mach_profile_listener(void *arg)
622
632
break ;
623
633
}
624
634
635
+ if (_dyld_dlopen_atfork_prepare != NULL && _dyld_dlopen_atfork_parent != NULL )
636
+ _dyld_dlopen_atfork_prepare ();
625
637
if (_dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
626
638
_dyld_atfork_prepare (); // briefly acquire the dlsym lock
627
639
host_thread_state_t state ;
628
640
int valid_thread = jl_thread_suspend_and_get_state2 (i , & state );
629
641
unw_context_t * uc = (unw_context_t * )& state ;
630
642
if (_dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
631
643
_dyld_atfork_parent (); // quickly release the dlsym lock
632
-
644
+ if (_dyld_dlopen_atfork_prepare != NULL && _dyld_dlopen_atfork_parent != NULL )
645
+ _dyld_dlopen_atfork_parent ();
646
+ if (!valid_thread )
647
+ continue ;
633
648
if (running ) {
634
649
#ifdef LLVMLIBUNWIND
635
650
/*
0 commit comments