Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 25 additions & 5 deletions src/signals-unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,14 +310,34 @@ int exc_reg_is_write_fault(uintptr_t esr) {
#include <sys/eventfd.h>
#include <link.h>

#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_))
Expand Down