@@ -36,6 +36,9 @@ extern int _keymgr_set_lockmode_processwide_ptr(unsigned int key, unsigned int m
3636extern  void  _dyld_atfork_prepare (void ) __attribute__((weak_import ));
3737extern  void  _dyld_atfork_parent (void ) __attribute__((weak_import ));
3838//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)); 
3942
4043static  void  attach_exception_port (thread_port_t  thread , int  segv_only );
4144
@@ -568,16 +571,23 @@ static int jl_lock_profile_mach(int dlsymlock)
568571    // workaround for old keymgr bugs 
569572    void  * unused  =  NULL ;
570573    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) 
572580    if  (dlsymlock  &&  _dyld_atfork_prepare  !=  NULL  &&  _dyld_atfork_parent  !=  NULL )
573581        _dyld_atfork_prepare ();
574582    return  keymgr_locked ;
575583}
576584
577585static  void  jl_unlock_profile_mach (int  dlsymlock , int  keymgr_locked )
578586{
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 ();
581591    if  (keymgr_locked )
582592        _keymgr_unlock_processwide_ptr (KEYMGR_GCC3_DW2_OBJ_LIST );
583593    jl_unlock_profile ();
@@ -622,14 +632,19 @@ void *mach_profile_listener(void *arg)
622632                break ;
623633            }
624634
635+             if  (_dyld_dlopen_atfork_prepare  !=  NULL  &&  _dyld_dlopen_atfork_parent  !=  NULL )
636+                 _dyld_dlopen_atfork_prepare ();
625637            if  (_dyld_atfork_prepare  !=  NULL  &&  _dyld_atfork_parent  !=  NULL )
626638                _dyld_atfork_prepare (); // briefly acquire the dlsym lock 
627639            host_thread_state_t  state ;
628640            int  valid_thread  =  jl_thread_suspend_and_get_state2 (i , & state );
629641            unw_context_t  * uc  =  (unw_context_t * )& state ;
630642            if  (_dyld_atfork_prepare  !=  NULL  &&  _dyld_atfork_parent  !=  NULL )
631643                _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 ;
633648            if  (running ) {
634649#ifdef  LLVMLIBUNWIND 
635650                /* 
0 commit comments