diff --git a/src/signals-unix.c b/src/signals-unix.c index c730f27f16def..1f4ad647a87af 100644 --- a/src/signals-unix.c +++ b/src/signals-unix.c @@ -310,14 +310,34 @@ int exc_reg_is_write_fault(uintptr_t esr) { #include #include +#ifndef _OS_FREEBSD_ +typedef struct { + void (*f)(void*) JL_NOTSAFEPOINT; + void *ctx; +} callback_t; +static int with_dl_iterate_phdr_lock(struct dl_phdr_info *info, size_t size, void *data) +{ + jl_lock_profile(); + callback_t *callback = (callback_t*)data; + callback->f(callback->ctx); + jl_unlock_profile(); + return 1; // only call this once +} +#endif + void jl_with_stackwalk_lock(void (*f)(void*), void *ctx) { - sigset_t sset, oset; - sigemptyset(&sset); - sigaddset(&sset, SIGUSR2); - pthread_sigmask(SIG_BLOCK, &sset, &oset); +#ifndef _OS_FREEBSD_ + callback_t callback = {f, ctx}; + dl_iterate_phdr(with_dl_iterate_phdr_lock, &callback); +#else + // FreeBSD makes the questionable decisions to use a terrible implementation of a spin + // lock and to block all signals while a lock is held. However, that also means it is + // not currently vulnerable to this libunwind bug that other platforms can encounter. + jl_lock_profile(); f(ctx); - pthread_sigmask(SIG_SETMASK, &oset, NULL); + jl_unlock_profile(); +#endif } #if defined(_OS_LINUX_) && (defined(_CPU_X86_64_) || defined(_CPU_X86_))