From 79f8abef59c1b683e342861aa6e574539ed83465 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 3 Feb 2025 15:05:42 -0500 Subject: [PATCH] restore non-freebsd-unix fix for profiling Restores #57035, undo #57089 for non-FreeBSD. While I suggested doing this change for all platforms, I forgot that means non-FreeBSD platforms become vulnerable again to the very deadlock problems that #57035 was required to prevent. That fix seems to not be viable on FreeBSD due to known libc implementation problems on that platform. However, upon closer inspection of the questionable design implementation decisions they seem to have made here, the platform is likely not currently vulnerable to this libunwind bug in the first place: https://github.com/lattera/freebsd/blob/master/libexec/rtld-elf/rtld_lock.c#L120 --- src/signals-unix.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) 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_))