@@ -303,41 +303,34 @@ int exc_reg_is_write_fault(uintptr_t esr) {
303303}
304304#endif
305305
306+ static int jl_thread_suspend_and_get_state (int tid , int timeout , bt_context_t * ctx );
307+
306308#if defined(HAVE_MACH )
307309#include "signals-mach.c"
308310#else
309311#include <poll.h>
310312#include <sys/eventfd.h>
311313#include <link.h>
312314
313- #ifndef _OS_FREEBSD_
314315typedef struct {
315- void (* f )(void * ) JL_NOTSAFEPOINT ;
316- void * ctx ;
317- } callback_t ;
316+ int16_t tid ;
317+ bt_context_t * ctx ;
318+ int success ;
319+ } callback_data_t ;
318320static int with_dl_iterate_phdr_lock (struct dl_phdr_info * info , size_t size , void * data )
319321{
320322 jl_lock_profile ();
321- callback_t * callback = (callback_t * )data ;
322- callback -> f ( callback -> ctx );
323+ callback_data_t * cb_data = (callback_data_t * )data ;
324+ cb_data -> success = jl_thread_suspend_and_get_state ( cb_data -> tid , 1 , cb_data -> ctx );
323325 jl_unlock_profile ();
324326 return 1 ; // only call this once
325327}
326- #endif
327328
328- void jl_with_stackwalk_lock ( void ( * f )( void * ), void * ctx )
329+ int jl_thread_suspend ( int16_t tid , bt_context_t * ctx )
329330{
330- #ifndef _OS_FREEBSD_
331- callback_t callback = {f , ctx };
332- dl_iterate_phdr (with_dl_iterate_phdr_lock , & callback );
333- #else
334- // FreeBSD makes the questionable decisions to use a terrible implementation of a spin
335- // lock and to block all signals while a lock is held. However, that also means it is
336- // not currently vulnerable to this libunwind bug that other platforms can encounter.
337- jl_lock_profile ();
338- f (ctx );
339- jl_unlock_profile ();
340- #endif
331+ callback_data_t cb_data = {tid , ctx , 0 };
332+ dl_iterate_phdr (with_dl_iterate_phdr_lock , & cb_data );
333+ return cb_data .success ;
341334}
342335
343336#if defined(_OS_LINUX_ ) && (defined(_CPU_X86_64_ ) || defined(_CPU_X86_ ))
@@ -458,7 +451,7 @@ static int exit_signal_cond = -1;
458451static int signal_caught_cond = -1 ;
459452static int signals_inflight = 0 ;
460453
461- int jl_thread_suspend_and_get_state (int tid , int timeout , bt_context_t * ctx )
454+ static int jl_thread_suspend_and_get_state (int tid , int timeout , bt_context_t * ctx )
462455{
463456 int err ;
464457 pthread_mutex_lock (& in_signal_lock );
@@ -845,15 +838,15 @@ void trigger_profile_peek(void)
845838
846839static jl_bt_element_t signal_bt_data [JL_MAX_BT_SIZE + 1 ];
847840static size_t signal_bt_size = 0 ;
848- static void do_critical_profile (void * ctx )
841+ static void do_critical_profile (void )
849842{
850843 bt_context_t signal_context ;
851844 // sample each thread, round-robin style in reverse order
852845 // (so that thread zero gets notified last)
853846 int nthreads = jl_atomic_load_acquire (& jl_n_threads );
854847 for (int i = nthreads ; i -- > 0 ; ) {
855848 // notify thread to stop
856- if (!jl_thread_suspend_and_get_state ( i , 1 , & signal_context ))
849+ if (!jl_thread_suspend ( i , & signal_context ))
857850 continue ;
858851
859852 // do backtrace on thread contexts for critical signals
@@ -866,7 +859,7 @@ static void do_critical_profile(void *ctx)
866859 }
867860}
868861
869- static void do_profile (void * ctx )
862+ static void do_profile (void )
870863{
871864 bt_context_t signal_context ;
872865 int nthreads = jl_atomic_load_acquire (& jl_n_threads );
@@ -883,7 +876,7 @@ static void do_profile(void *ctx)
883876 return ;
884877 }
885878 // notify thread to stop
886- if (!jl_thread_suspend_and_get_state (tid , 1 , & signal_context ))
879+ if (!jl_thread_suspend (tid , & signal_context ))
887880 return ;
888881 // unwinding can fail, so keep track of the current state
889882 // and restore from the SEGV handler if anything happens.
@@ -1062,15 +1055,15 @@ static void *signal_listener(void *arg)
10621055 signal_bt_size = 0 ;
10631056#if !defined(JL_DISABLE_LIBUNWIND )
10641057 if (critical ) {
1065- jl_with_stackwalk_lock ( do_critical_profile , NULL );
1058+ do_critical_profile ( );
10661059 }
10671060 else if (profile ) {
10681061 if (profile_all_tasks ) {
10691062 // Don't take the stackwalk lock here since it's already taken in `jl_rec_backtrace`
10701063 jl_profile_task ();
10711064 }
10721065 else {
1073- jl_with_stackwalk_lock ( do_profile , NULL );
1066+ do_profile ( );
10741067 }
10751068 }
10761069#ifndef HAVE_MACH
0 commit comments