Skip to content

Commit

Permalink
Implement jl_call_in_ctx on unix.
Browse files Browse the repository at this point in the history
Use it to make sure that `jl_rethrow` and `jl_exit` are running on the right
thread and right stack when an exception/exit is caused by a signal.

Fix #17706
  • Loading branch information
yuyichao committed Aug 2, 2016
1 parent 1e45a62 commit 82f0b93
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 63 deletions.
3 changes: 0 additions & 3 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,6 @@ void jl_call_tracer(tracer_cb callback, jl_value_t *tracee);

extern size_t jl_page_size;
extern jl_function_t *jl_typeinf_func;
#if defined(JL_USE_INTEL_JITEVENTS)
extern unsigned sig_stack_size;
#endif

JL_DLLEXPORT extern int jl_lineno;
JL_DLLEXPORT extern const char *jl_filename;
Expand Down
86 changes: 67 additions & 19 deletions src/signals-mach.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
#include <sys/_structs.h>
#endif

static void attach_exception_port(thread_port_t thread);
static void attach_exception_port(thread_port_t thread, int segv_only);

#ifdef JULIA_ENABLE_THREADING
// low 16 bits are the thread id, the next 8 bits are the original gc_state
Expand Down Expand Up @@ -99,7 +99,7 @@ static void allocate_segv_handler()
}
pthread_attr_destroy(&attr);
for (int16_t tid = 0;tid < jl_n_threads;tid++) {
attach_exception_port(pthread_mach_thread_np(jl_all_tls_states[tid]->system_id));
attach_exception_port(pthread_mach_thread_np(jl_all_tls_states[tid]->system_id), 0);
}
}

Expand All @@ -120,7 +120,21 @@ enum x86_trap_flags {
PAGE_PRESENT = 0x1
};

void jl_throw_in_thread(int tid, mach_port_t thread, jl_value_t *exception)
static void jl_call_in_state(jl_ptls_t ptls2, x86_thread_state64_t *state,
void (*fptr)(void))
{
uint64_t rsp = (uint64_t)ptls2->signal_stack + sig_stack_size;
assert(rsp % 16 == 0);

// push (null) $RIP onto the stack
rsp -= sizeof(void*);
*(void**)rsp = NULL;

state->__rsp = rsp; // set stack pointer
state->__rip = (uint64_t)fptr; // "call" the function
}

static void jl_throw_in_thread(int tid, mach_port_t thread, jl_value_t *exception)
{
unsigned int count = MACHINE_THREAD_STATE_COUNT;
x86_thread_state64_t state;
Expand All @@ -131,18 +145,9 @@ void jl_throw_in_thread(int tid, mach_port_t thread, jl_value_t *exception)
ptls2->bt_size = rec_backtrace_ctx(ptls2->bt_data, JL_MAX_BT_SIZE,
(bt_context_t*)&state);
ptls2->exception_in_transit = exception;

uint64_t rsp = (uint64_t)ptls2->signal_stack + sig_stack_size;
rsp &= -16; // ensure 16-byte alignment

// push (null) $RIP onto the stack
rsp -= sizeof(void*);
*(void**)rsp = NULL;

state.__rsp = rsp; // set stack pointer
state.__rip = (uint64_t)&jl_rethrow; // "call" the function

ret = thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t)&state, count);
jl_call_in_state(ptls2, &state, &jl_rethrow);
ret = thread_set_state(thread, x86_THREAD_STATE64,
(thread_state_t)&state, count);
HANDLE_MACH_ERROR("thread_set_state",ret);
}

Expand Down Expand Up @@ -185,6 +190,11 @@ kern_return_t catch_exception_raise(mach_port_t exception_port,
jl_ptls_t ptls2 = &jl_tls_states;
tid = 0;
#endif
if (exception == EXC_ARITHMETIC) {
jl_throw_in_thread(tid, thread, jl_diverror_exception);
return KERN_SUCCESS;
}
assert(exception == EXC_BAD_ACCESS);
kern_return_t ret = thread_get_state(thread, x86_EXCEPTION_STATE64, (thread_state_t)&exc_state, &exc_count);
HANDLE_MACH_ERROR("thread_get_state", ret);
uint64_t fault_addr = exc_state.__faultvaddr;
Expand Down Expand Up @@ -237,11 +247,14 @@ kern_return_t catch_exception_raise(mach_port_t exception_port,
}
}

static void attach_exception_port(thread_port_t thread)
static void attach_exception_port(thread_port_t thread, int segv_only)
{
kern_return_t ret;
// http://www.opensource.apple.com/source/xnu/xnu-2782.1.97/osfmk/man/thread_set_exception_ports.html
ret = thread_set_exception_ports(thread, EXC_MASK_BAD_ACCESS, segv_port, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
exception_mask_t mask = EXC_MASK_BAD_ACCESS;
if (!segv_only)
mask |= EXC_MASK_ARITHMETIC;
ret = thread_set_exception_ports(thread, mask, segv_port, EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
HANDLE_MACH_ERROR("thread_set_exception_ports", ret);
}

Expand Down Expand Up @@ -283,7 +296,7 @@ static void jl_try_deliver_sigint(void)
kern_return_t ret = thread_suspend(thread);
HANDLE_MACH_ERROR("thread_suspend", ret);

// This abort `sleep` and other syscall.
// This abort `sleep` and other syscalls.
ret = thread_abort(thread);
HANDLE_MACH_ERROR("thread_abort", ret);

Expand All @@ -304,6 +317,41 @@ static void jl_try_deliver_sigint(void)
HANDLE_MACH_ERROR("thread_resume", ret);
}

static void jl_exit_thread0(int exitstate)
{
jl_ptls_t ptls2 = jl_all_tls_states[0];
mach_port_t thread = pthread_mach_thread_np(ptls2->system_id);
kern_return_t ret = thread_suspend(thread);
HANDLE_MACH_ERROR("thread_suspend", ret);

// This abort `sleep` and other syscalls.
ret = thread_abort(thread);
HANDLE_MACH_ERROR("thread_abort", ret);

unsigned int count = MACHINE_THREAD_STATE_COUNT;
x86_thread_state64_t state;
ret = thread_get_state(thread, x86_THREAD_STATE64,
(thread_state_t)&state, &count);

void (*exit_func)(int) = &_exit;
if (thread0_exit_count <= 1) {
exit_func = &jl_exit;
}
else if (thread0_exit_count == 2) {
exit_func = &exit;
}

// First integer argument. Not portable but good enough =)
state.__rdi = exitstate;
jl_call_in_state(ptls2, &state, (void (*)(void))exit_func);
ret = thread_set_state(thread, x86_THREAD_STATE64,
(thread_state_t)&state, count);
HANDLE_MACH_ERROR("thread_set_state",ret);

ret = thread_resume(thread);
HANDLE_MACH_ERROR("thread_resume", ret);
}

static int profile_started = 0;
mach_timespec_t timerprof;
static pthread_t profiler_thread;
Expand Down Expand Up @@ -363,7 +411,7 @@ void *mach_profile_listener(void *arg)
(void)arg;
int i;
const int max_size = 512;
attach_exception_port(mach_thread_self());
attach_exception_port(mach_thread_self(), 1);
#ifdef LIBOSXUNWIND
mach_profiler_thread = mach_thread_self();
#endif
Expand Down
Loading

0 comments on commit 82f0b93

Please sign in to comment.