diff --git a/src/init.c b/src/init.c index 4cec87e7d1bbb..a1a3601969a37 100644 --- a/src/init.c +++ b/src/init.c @@ -88,46 +88,10 @@ jl_options_t jl_options = { 0, // quiet int jl_boot_file_loaded = 0; size_t jl_page_size; -void jl_init_stack_limits(void) +void jl_init_stack_limits(int ismaster) { -#if defined(_OS_LINUX_) - pthread_attr_t attr; - if (pthread_getattr_np(pthread_self(), &attr)) { - // On linux `pthread_getattr_np` can fail on master thread if - // `/proc/self/maps` is not readable, in which case we fall back to - // `rlimit` - struct rlimit rl; - getrlimit(RLIMIT_STACK, &rl); - jl_stack_hi = (char*)&attr; - jl_stack_lo = jl_stack_hi - rl.rlim_cur; - } - else { - void *stackaddr; - size_t stacksize; - pthread_attr_getstack(&attr, &stackaddr, &stacksize); - pthread_attr_destroy(&attr); - jl_stack_lo = (char*)stackaddr; - jl_stack_hi = (char*)stackaddr + stacksize; - } -#elif defined(_OS_DARWIN_) - extern void *pthread_get_stackaddr_np(pthread_t thread); - extern size_t pthread_get_stacksize_np(pthread_t thread); - pthread_t thread = pthread_self(); - void *stackaddr = pthread_get_stackaddr_np(thread); - size_t stacksize = pthread_get_stacksize_np(thread); - jl_stack_lo = (char*)stackaddr; - jl_stack_hi = (char*)stackaddr + stacksize; -#elif defined(_OS_FREEBSD_) - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_get_np(pthread_self(), &attr); - void *stackaddr; - size_t stacksize; - pthread_attr_getstack(&attr, &stackaddr, &stacksize); - pthread_attr_destroy(&attr); - jl_stack_lo = (char*)stackaddr; - jl_stack_hi = (char*)stackaddr + stacksize; -#elif defined(_OS_WINDOWS_) +#ifdef _OS_WINDOWS_ + (void)ismaster; # ifdef _COMPILER_MICROSOFT_ # ifdef _P64 void **tib = (void**)__readgsqword(0x30); @@ -147,7 +111,46 @@ void jl_init_stack_limits(void) jl_stack_lo = (char*)tib[2]; // Stack Limit / Ceiling of stack (low address) #else # ifdef JULIA_ENABLE_THREADING -# warning "Getting stack size for thread is not supported." + // Only use pthread_*_np functions to get stack address for non-master + // threads since it seems to return bogus values for master thread on Linux + // and possibly OSX. + if (!ismaster) { +# if defined(_OS_LINUX_) + pthread_attr_t attr; + pthread_getattr_np(pthread_self(), &attr); + void *stackaddr; + size_t stacksize; + pthread_attr_getstack(&attr, &stackaddr, &stacksize); + pthread_attr_destroy(&attr); + jl_stack_lo = (char*)stackaddr; + jl_stack_hi = (char*)stackaddr + stacksize; + return; +# elif defined(_OS_DARWIN_) + extern void *pthread_get_stackaddr_np(pthread_t thread); + extern size_t pthread_get_stacksize_np(pthread_t thread); + pthread_t thread = pthread_self(); + void *stackaddr = pthread_get_stackaddr_np(thread); + size_t stacksize = pthread_get_stacksize_np(thread); + jl_stack_lo = (char*)stackaddr; + jl_stack_hi = (char*)stackaddr + stacksize; + return; +# elif defined(_OS_FREEBSD_) + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_get_np(pthread_self(), &attr); + void *stackaddr; + size_t stacksize; + pthread_attr_getstack(&attr, &stackaddr, &stacksize); + pthread_attr_destroy(&attr); + jl_stack_lo = (char*)stackaddr; + jl_stack_hi = (char*)stackaddr + stacksize; + return; +# else +# warning "Getting stack size for thread is not supported." +# endif + } +# else + (void)ismaster; # endif struct rlimit rl; getrlimit(RLIMIT_STACK, &rl); @@ -180,7 +183,7 @@ static void jl_find_stack_bottom(void) } #endif #endif - jl_init_stack_limits(); + jl_init_stack_limits(1); } struct uv_shutdown_queue_item { uv_handle_t *h; struct uv_shutdown_queue_item *next; }; diff --git a/src/julia_internal.h b/src/julia_internal.h index a85d5d1c4575e..233b153955113 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -228,7 +228,7 @@ void jl_init_primitives(void); void jl_init_codegen(void); void jl_init_intrinsic_functions(void); void jl_init_tasks(void); -void jl_init_stack_limits(void); +void jl_init_stack_limits(int ismaster); void jl_init_root_task(void *stack, size_t ssize); void jl_init_serializer(void); void jl_gc_init(void); diff --git a/src/signals-mach.c b/src/signals-mach.c index 9bdc692b5d4c2..8f32afd15356d 100644 --- a/src/signals-mach.c +++ b/src/signals-mach.c @@ -116,6 +116,17 @@ kern_return_t catch_exception_raise(mach_port_t exception_port, if (thread == mach_profiler_thread) { return profiler_segv_handler(exception_port, thread, task, exception, code, code_count); } +#endif +#ifdef JULIA_ENABLE_THREADING + jl_tls_states_t *ptls = NULL; + for (int16_t tid = 0;tid < jl_n_threads;tid++) { + if (pthread_mach_thread_np(jl_all_task_states[tid].system_id) == thread) { + ptls = jl_all_task_states[tid].ptls; + break; + } + } +#else + jl_tls_states_t *ptls = &jl_tls_states; #endif 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); @@ -126,7 +137,7 @@ kern_return_t catch_exception_raise(mach_port_t exception_port, if (msync((void*)(fault_addr & ~(jl_page_size - 1)), 1, MS_ASYNC) == 0) { // check if this was a valid address #endif jl_value_t *excpt; - if (is_addr_on_stack((void*)fault_addr)) { + if (is_addr_on_stack(ptls, (void*)fault_addr)) { excpt = jl_stackovf_exception; } #ifdef SEGV_EXCEPTION diff --git a/src/signals-unix.c b/src/signals-unix.c index e097a25ae4c1f..94cf958648c29 100644 --- a/src/signals-unix.c +++ b/src/signals-unix.c @@ -35,14 +35,14 @@ unsigned sig_stack_size = SIGSTKSZ; static pthread_t signals_thread; static volatile int remote_sig; -static int is_addr_on_stack(void *addr) +static int is_addr_on_stack(jl_tls_states_t *ptls, void *addr) { #ifdef COPY_STACKS - return ((char*)addr > (char*)jl_stack_lo-3000000 && - (char*)addr < (char*)jl_stack_hi); + return ((char*)addr > (char*)ptls->stack_lo-3000000 && + (char*)addr < (char*)ptls->stack_hi); #else - return ((char*)addr > (char*)jl_current_task->stkbuf && - (char*)addr < (char*)jl_current_task->stkbuf + jl_current_task->ssize); + return ((char*)addr > (char*)ptls->current_task->stkbuf && + (char*)addr < (char*)ptls->current_task->stkbuf + ptls->current_task->ssize); #endif } @@ -75,7 +75,7 @@ static void segv_handler(int sig, siginfo_t *info, void *context) sigset_t sset; assert(sig == SIGSEGV); - if (jl_in_jl_ || is_addr_on_stack(info->si_addr)) { // stack overflow, or restarting jl_ + if (jl_in_jl_ || is_addr_on_stack(jl_get_ptls_states(), info->si_addr)) { // stack overflow, or restarting jl_ sigemptyset(&sset); sigaddset(&sset, SIGSEGV); sigprocmask(SIG_UNBLOCK, &sset, NULL); diff --git a/src/threading.c b/src/threading.c index d9d753f10a0ef..84e22c8e1adb6 100644 --- a/src/threading.c +++ b/src/threading.c @@ -216,7 +216,7 @@ void ti_threadfun(void *arg) // initialize this thread (set tid, create heap, etc.) ti_initthread(ta->tid); - jl_init_stack_limits(); + jl_init_stack_limits(0); // set up tasking jl_init_root_task(jl_stack_lo, jl_stack_hi - jl_stack_lo);