@@ -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
@@ -564,16 +567,23 @@ static int jl_lock_profile_mach(int dlsymlock)
564
567
// workaround for old keymgr bugs
565
568
void * unused = NULL ;
566
569
int keymgr_locked = _keymgr_get_and_lock_processwide_ptr_2 (KEYMGR_GCC3_DW2_OBJ_LIST , & unused ) == 0 ;
567
- // workaround for new dlsym4 bugs (API and bugs introduced in macOS 12.1)
570
+ // workaround for new dlsym4 bugs in the workaround for dlsym bugs: _dyld_atfork_prepare
571
+ // acquires its locks in the wrong order, but fortunately we happen to able to guard it
572
+ // with this call to force it to prevent that TSAN violation from causing a deadlock
573
+ if (dlsymlock && _dyld_dlopen_atfork_prepare != NULL && _dyld_dlopen_atfork_parent != NULL )
574
+ _dyld_dlopen_atfork_prepare ();
575
+ // workaround for new dlsym4 bugs (API and bugs introduced circa macOS 12.1)
568
576
if (dlsymlock && _dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
569
577
_dyld_atfork_prepare ();
570
578
return keymgr_locked ;
571
579
}
572
580
573
581
static void jl_unlock_profile_mach (int dlsymlock , int keymgr_locked )
574
582
{
575
- if (dlsymlock && _dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL ) \
576
- _dyld_atfork_parent (); \
583
+ if (dlsymlock && _dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
584
+ _dyld_atfork_parent ();
585
+ if (dlsymlock && _dyld_dlopen_atfork_prepare != NULL && _dyld_dlopen_atfork_parent != NULL )
586
+ _dyld_dlopen_atfork_parent ();
577
587
if (keymgr_locked )
578
588
_keymgr_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST );
579
589
jl_unlock_profile ();
@@ -618,6 +628,8 @@ void *mach_profile_listener(void *arg)
618
628
break ;
619
629
}
620
630
631
+ if (_dyld_dlopen_atfork_prepare != NULL && _dyld_dlopen_atfork_parent != NULL )
632
+ _dyld_dlopen_atfork_prepare ();
621
633
if (_dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
622
634
_dyld_atfork_prepare (); // briefly acquire the dlsym lock
623
635
host_thread_state_t state ;
@@ -626,7 +638,10 @@ void *mach_profile_listener(void *arg)
626
638
unw_context_t * uc = (unw_context_t * )& state ;
627
639
if (_dyld_atfork_prepare != NULL && _dyld_atfork_parent != NULL )
628
640
_dyld_atfork_parent (); // quickly release the dlsym lock
629
-
641
+ if (_dyld_dlopen_atfork_prepare != NULL && _dyld_dlopen_atfork_parent != NULL )
642
+ _dyld_dlopen_atfork_parent ();
643
+ if (!valid_thread )
644
+ continue ;
630
645
if (running ) {
631
646
#ifdef LLVMLIBUNWIND
632
647
/*
0 commit comments