From e5983d77cd5bef4b7ff5f0cec22d008d0cb3922d Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Tue, 30 May 2017 22:47:24 -0400 Subject: [PATCH] Handle safe_restore on Windows and macOS on managed threads --- src/signal-handling.c | 12 ++++++------ src/signals-mach.c | 14 ++++++++++---- src/signals-win.c | 16 ++++++++++++---- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/signal-handling.c b/src/signal-handling.c index e6edffd1f83d3..d8d0bf553889d 100644 --- a/src/signal-handling.c +++ b/src/signal-handling.c @@ -170,9 +170,9 @@ void jl_show_sigill(void *_ctx) } #elif defined(_OS_LINUX_) && defined(_CPU_AARCH64_) uint32_t inst = 0; - size_t len = jl_safe_read_mem(ptr, (char*)&inst, 4); + size_t len = jl_safe_read_mem(pc, (char*)&inst, 4); if (len < 4) - jl_safe_printf("Fault when reading instruction: %d bytes read\n". (int)len); + jl_safe_printf("Fault when reading instruction: %d bytes read\n", (int)len); if (inst == 0xd4200020) { // brk #0x1 // The signal might actually be SIGTRAP instead, doesn't hurt to handle it here though. jl_safe_printf("Unreachable reached at %p\n", pc); @@ -185,9 +185,9 @@ void jl_show_sigill(void *_ctx) if (ctx->uc_mcontext.arm_cpsr & (1 << 5)) { // Thumb uint16_t inst[2] = {0, 0}; - size_t len = jl_safe_read_mem(ptr, (char*)&inst, 4); + size_t len = jl_safe_read_mem(pc, (char*)&inst, 4); if (len < 2) - jl_safe_printf("Fault when reading Thumb instruction: %d bytes read\n". (int)len); + jl_safe_printf("Fault when reading Thumb instruction: %d bytes read\n", (int)len); // LLVM and GCC uses different code for the trap... if (inst[0] == 0xdefe || inst[0] == 0xdeff) { // The signal might actually be SIGTRAP instead, doesn't hurt to handle it here though. @@ -201,9 +201,9 @@ void jl_show_sigill(void *_ctx) } else { uint32_t inst = 0; - size_t len = jl_safe_read_mem(ptr, (char*)&inst, 4); + size_t len = jl_safe_read_mem(pc, (char*)&inst, 4); if (len < 4) - jl_safe_printf("Fault when reading instruction: %d bytes read\n". (int)len); + jl_safe_printf("Fault when reading instruction: %d bytes read\n", (int)len); // LLVM and GCC uses different code for the trap... if (inst == 0xe7ffdefe || inst == 0xe7f000f0) { // The signal might actually be SIGTRAP instead, doesn't hurt to handle it here though. diff --git a/src/signals-mach.c b/src/signals-mach.c index eb88e187b7505..8534eb6e8bafe 100644 --- a/src/signals-mach.c +++ b/src/signals-mach.c @@ -141,10 +141,12 @@ static void jl_throw_in_thread(int tid, mach_port_t thread, jl_value_t *exceptio kern_return_t ret = thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t)&state, &count); HANDLE_MACH_ERROR("thread_get_state", ret); jl_ptls_t ptls2 = jl_all_tls_states[tid]; - - ptls2->bt_size = rec_backtrace_ctx(ptls2->bt_data, JL_MAX_BT_SIZE, - (bt_context_t*)&state); - ptls2->exception_in_transit = exception; + if (!ptls2->safe_restore) { + assert(exception); + ptls2->bt_size = rec_backtrace_ctx(ptls2->bt_data, JL_MAX_BT_SIZE, + (bt_context_t*)&state); + ptls2->exception_in_transit = exception; + } jl_call_in_state(ptls2, &state, &jl_rethrow); ret = thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t)&state, count); @@ -214,6 +216,10 @@ kern_return_t catch_exception_raise(mach_port_t exception_port, } return KERN_SUCCESS; } + if (ptls2->safe_restore) { + jl_throw_in_thread(tid, thread, jl_stackovf_exception); + return KERN_SUCCESS; + } #ifdef SEGV_EXCEPTION if (1) { #else diff --git a/src/signals-win.c b/src/signals-win.c index 6b056b340bd29..0672da59a17cb 100644 --- a/src/signals-win.c +++ b/src/signals-win.c @@ -86,6 +86,8 @@ void __cdecl crt_sig_handler(int sig, int num) } break; default: // SIGSEGV, (SSIGTERM, IGILL) + if (ptls->safe_restore) + jl_rethrow(); memset(&Context, 0, sizeof(Context)); RtlCaptureContext(&Context); if (sig == SIGILL) @@ -107,7 +109,6 @@ void restore_signals(void) void jl_throw_in_ctx(jl_value_t *excpt, CONTEXT *ctxThread, int bt) { jl_ptls_t ptls = jl_get_ptls_states(); - assert(excpt != NULL); #if defined(_CPU_X86_64_) DWORD64 Rsp = (ctxThread->Rsp&(DWORD64)-16) - 8; #elif defined(_CPU_X86_) @@ -115,9 +116,12 @@ void jl_throw_in_ctx(jl_value_t *excpt, CONTEXT *ctxThread, int bt) #else #error WIN16 not supported :P #endif - ptls->bt_size = bt ? rec_backtrace_ctx(ptls->bt_data, JL_MAX_BT_SIZE, - ctxThread) : 0; - ptls->exception_in_transit = excpt; + if (!ptls->safe_restore) { + assert(excpt != NULL); + ptls->bt_size = bt ? rec_backtrace_ctx(ptls->bt_data, JL_MAX_BT_SIZE, + ctxThread) : 0; + ptls->exception_in_transit = excpt; + } #if defined(_CPU_X86_64_) *(DWORD64*)Rsp = 0; ctxThread->Rsp = Rsp; @@ -222,6 +226,10 @@ static LONG WINAPI _exception_handler(struct _EXCEPTION_POINTERS *ExceptionInfo, } return EXCEPTION_CONTINUE_EXECUTION; } + if (ptls->safe_restore) { + jl_throw_in_ctx(NULL, ExceptionInfo->ContextRecord, in_ctx); + return EXCEPTION_CONTINUE_EXECUTION; + } if (ExceptionInfo->ExceptionRecord->ExceptionInformation[0] == 1) { // writing to read-only memory (e.g. mmap) jl_throw_in_ctx(jl_readonlymemory_exception, ExceptionInfo->ContextRecord,in_ctx);