Skip to content

Commit

Permalink
Block thread from receiving profile signal with stackwalk lock (#57089)
Browse files Browse the repository at this point in the history
This is Jameson's proposed amendment to the changes made in #57035 that
introduced a deadlock on FreeBSD, amusingly in service of fixing a
deadlock on Linux.

On Linux and (non-macOS) BSD, instead of acquiring and releasing a lock
on the profiler in `jl_with_stackwalk_lock`, we're just blocking the
thread from receiving the profiler's `SIGUSR2` signal at all.

This should fix #57058; I don't get the deadlock locally on FreeBSD with
this change, but it's AArch64 instead of x86-64 like on CI, so let's see
if this also makes CI happy. If so, closes #57059.

Co-authored-by: Jameson Nash <vtjnash@gmail.com>
  • Loading branch information
ararslan and vtjnash authored Jan 18, 2025
1 parent 1262bf8 commit 1740287
Showing 1 changed file with 6 additions and 15 deletions.
21 changes: 6 additions & 15 deletions src/signals-unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,23 +310,14 @@ int exc_reg_is_write_fault(uintptr_t esr) {
#include <sys/eventfd.h>
#include <link.h>

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
}

void jl_with_stackwalk_lock(void (*f)(void*), void *ctx)
{
callback_t callback = {f, ctx};
dl_iterate_phdr(with_dl_iterate_phdr_lock, &callback);
sigset_t sset, oset;
sigemptyset(&sset);
sigaddset(&sset, SIGUSR2);
pthread_sigmask(SIG_BLOCK, &sset, &oset);
f(ctx);
pthread_sigmask(SIG_SETMASK, &oset, NULL);
}

#if defined(_OS_LINUX_) && (defined(_CPU_X86_64_) || defined(_CPU_X86_))
Expand Down

0 comments on commit 1740287

Please sign in to comment.