// request: // 0: nothing // 1: get state // 2: throw sigint if `!defer_signal && io_wait` or if force throw threshold // is reached // 3: exit with `thread0_exit_state` void usr2_handler(int sig, siginfo_t *info, void *ctx) { jl_ptls_t ptls = jl_get_ptls_states(); sig_atomic_t request = jl_atomic_exchange(&ptls->signal_request, 0); if (request == 1) { signal_context = jl_to_bt_context(ctx); pthread_mutex_lock(&in_signal_lock); pthread_cond_broadcast(&signal_caught_cond); pthread_cond_wait(&exit_signal_cond, &in_signal_lock); request = jl_atomic_exchange(&ptls->signal_request, 0); assert(request == 1); (void)request; pthread_cond_broadcast(&signal_caught_cond); pthread_mutex_unlock(&in_signal_lock); } else if (request == 2) { jl_unblock_signal(sig); int force = jl_check_force_sigint(); if (force || (!ptls->defer_signal && ptls->io_wait)) { jl_safepoint_consume_sigint(); if (force) jl_safe_printf("WARNING: Force throwing a SIGINT\n"); // Force a throw jl_clear_force_sigint(); jl_throw_in_ctx(ptls, jl_interrupt_exception, ctx); } } else if (request == 3) { jl_unblock_signal(sig); jl_call_in_ctx(ptls, jl_exit_thread0_cb, ctx); } }
static void segv_handler(int sig, siginfo_t *info, void *context) { assert(sig == SIGSEGV || sig == SIGBUS); #ifdef JULIA_ENABLE_THREADING if (info->si_addr == jl_gc_signal_page) { jl_unblock_signal(sig); jl_gc_signal_wait(); return; } #endif if (jl_safe_restore || is_addr_on_stack(jl_get_ptls_states(), info->si_addr)) { // stack overflow, or restarting jl_ jl_unblock_signal(sig); jl_throw(jl_stackovf_exception); } else if (sig == SIGSEGV && info->si_code == SEGV_ACCERR) { // writing to read-only memory (e.g., mmap) jl_unblock_signal(sig); jl_throw(jl_readonlymemory_exception); } else { #ifdef SEGV_EXCEPTION jl_unblock_signal(sig); jl_throw(jl_segv_exception); #else sigdie_handler(sig, info, context); #endif } }
static void segv_handler(int sig, siginfo_t *info, void *context) { jl_ptls_t ptls = jl_get_ptls_states(); assert(sig == SIGSEGV || sig == SIGBUS); if (jl_addr_is_safepoint((uintptr_t)info->si_addr)) { jl_unblock_signal(sig); #ifdef JULIA_ENABLE_THREADING jl_set_gc_and_wait(); // Do not raise sigint on worker thread if (ptls->tid != 0) return; #endif if (ptls->defer_signal) { jl_safepoint_defer_sigint(); } else if (jl_safepoint_consume_sigint()) { jl_clear_force_sigint(); jl_throw_in_ctx(ptls, jl_interrupt_exception, context); } return; } if (ptls->safe_restore || is_addr_on_stack(ptls, info->si_addr)) { // stack overflow, or restarting jl_ jl_unblock_signal(sig); jl_throw_in_ctx(ptls, jl_stackovf_exception, context); } else if (jl_is_on_sigstack(ptls, info->si_addr, context)) { // This mainly happens when one of the finalizers during final cleanup // on the signal stack has a deep/infinite recursion. // There isn't anything more we can do // (we are already corrupting that stack running this function) // so just call `_exit` to terminate immediately. jl_safe_printf("ERROR: Signal stack overflow, exit\n"); _exit(sig + 128); } else if (sig == SIGSEGV && info->si_code == SEGV_ACCERR) { // writing to read-only memory (e.g., mmap) jl_unblock_signal(sig); jl_throw_in_ctx(ptls, jl_readonlymemory_exception, context); } else { #ifdef SEGV_EXCEPTION jl_unblock_signal(sig); jl_throw_in_ctx(ptls, jl_segv_exception, context); #else sigdie_handler(sig, info, context); #endif } }
void fpe_handler(int sig, siginfo_t *info, void *context) { (void)info; jl_ptls_t ptls = jl_get_ptls_states(); jl_unblock_signal(sig); jl_throw_in_ctx(ptls, jl_diverror_exception, context); }
void usr2_handler(int sig, siginfo_t *info, void *ctx) { ucontext_t *context = (ucontext_t*)ctx; if ((remote_sig > 0 && waiting_for < 0) || waiting_for == ti_tid) { int realsig = remote_sig; #ifdef __APPLE__ signal_context = (unw_context_t*)&context->uc_mcontext->__ss; #else signal_context = (unw_context_t*)context; #endif pthread_mutex_lock(&in_signal_lock); wait_barrier(); pthread_cond_wait(&exit_signal_cond, &in_signal_lock); wait_barrier(); pthread_mutex_unlock(&in_signal_lock); if (ti_tid == 0 && realsig == SIGINT) { if (jl_defer_signal) { jl_signal_pending = realsig; } else { jl_signal_pending = 0; jl_unblock_signal(sig); jl_throw(jl_interrupt_exception); } } } }
static void segv_handler(int sig, siginfo_t *info, void *context) { jl_ptls_t ptls = jl_get_ptls_states(); assert(sig == SIGSEGV || sig == SIGBUS); if (jl_addr_is_safepoint((uintptr_t)info->si_addr)) { jl_unblock_signal(sig); #ifdef JULIA_ENABLE_THREADING jl_set_gc_and_wait(); // Do not raise sigint on worker thread if (ptls->tid != 0) return; #endif if (jl_get_ptls_states()->defer_signal) { jl_safepoint_defer_sigint(); } else if (jl_safepoint_consume_sigint()) { jl_clear_force_sigint(); jl_throw_in_ctx(jl_interrupt_exception, context); } return; } if (ptls->safe_restore || is_addr_on_stack(jl_get_ptls_states(), info->si_addr)) { // stack overflow, or restarting jl_ jl_unblock_signal(sig); jl_throw_in_ctx(jl_stackovf_exception, context); } else if (sig == SIGSEGV && info->si_code == SEGV_ACCERR) { // writing to read-only memory (e.g., mmap) jl_unblock_signal(sig); jl_throw_in_ctx(jl_readonlymemory_exception, context); } else { #ifdef SEGV_EXCEPTION jl_unblock_signal(sig); jl_throw_in_ctx(jl_segv_exception, context); #else sigdie_handler(sig, info, context); #endif } }
void fpe_handler(int sig, siginfo_t *info, void *context) { (void)info; jl_unblock_signal(sig); jl_throw_in_ctx(jl_diverror_exception, context); }
void fpe_handler(int arg) { (void)arg; jl_unblock_signal(SIGFPE); jl_throw(jl_diverror_exception); }