diff --git a/src/signals-unix.c b/src/signals-unix.c index 0fafe121cd9b6..230c0cb2dada5 100644 --- a/src/signals-unix.c +++ b/src/signals-unix.c @@ -89,6 +89,14 @@ static void jl_call_in_ctx(jl_ptls_t ptls, void (*fptr)(void), int sig, void *_c // checks that the syscall is made in the signal handler and that // the ucontext address is valid. Hopefully the value of the ucontext // will not be part of the validation... + if (!ptls->signal_stack) { + sigset_t sset; + sigemptyset(&sset); + sigaddset(&sset, sig); + sigprocmask(SIG_UNBLOCK, &sset, NULL); + fptr(); + return; + } uintptr_t rsp = (uintptr_t)ptls->signal_stack + sig_stack_size; assert(rsp % 16 == 0); #if defined(_OS_LINUX_) && defined(_CPU_X86_64_) @@ -667,9 +675,22 @@ static void *signal_listener(void *arg) // do backtrace for profiler if (profile && running) { if (bt_size_cur < bt_size_max - 1) { - // Get backtrace data - bt_size_cur += rec_backtrace_ctx((uintptr_t*)bt_data_prof + bt_size_cur, - bt_size_max - bt_size_cur - 1, signal_context); + // unwinding can fail, so keep track of the current state + // and restore from the SEGV handler if anything happens. + jl_ptls_t ptls = jl_get_ptls_states(); + jl_jmp_buf *old_buf = ptls->safe_restore; + jl_jmp_buf buf; + + ptls->safe_restore = &buf; + if (jl_setjmp(buf, 0)) { + jl_safe_printf("WARNING: profiler attempt to access an invalid memory location\n"); + } else { + // Get backtrace data + bt_size_cur += rec_backtrace_ctx((uintptr_t*)bt_data_prof + bt_size_cur, + bt_size_max - bt_size_cur - 1, signal_context); + } + ptls->safe_restore = old_buf; + // Mark the end of this block with 0 bt_data_prof[bt_size_cur++] = 0; }