Skip to content

Commit

Permalink
Handle safe_restore on Windows and macOS on managed threads
Browse files Browse the repository at this point in the history
  • Loading branch information
yuyichao committed May 31, 2017
1 parent f611cfc commit e5983d7
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 14 deletions.
12 changes: 6 additions & 6 deletions src/signal-handling.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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.
Expand All @@ -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.
Expand Down
14 changes: 10 additions & 4 deletions src/signals-mach.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down
16 changes: 12 additions & 4 deletions src/signals-win.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -107,17 +109,19 @@ 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_)
DWORD32 Esp = (ctxThread->Esp&(DWORD32)-16) - 4;
#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;
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit e5983d7

Please sign in to comment.