// request: // 0: nothing // 1: get state // 3: throw sigint if `!defer_signal && io_wait` or if force throw threshold // is reached void usr2_handler(int sig, siginfo_t *info, void *ctx) { jl_tls_states_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(jl_interrupt_exception, ctx); } } }
static void jl_try_throw_sigint(void) { jl_ptls_t ptls = jl_get_ptls_states(); jl_safepoint_enable_sigint(); jl_wake_libuv(); 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(jl_interrupt_exception); } }
// Try to throw the exception in the master thread. static void jl_try_deliver_sigint(void) { jl_ptls_t ptls2 = jl_all_tls_states[0]; jl_safepoint_enable_sigint(); jl_wake_libuv(); if ((DWORD)-1 == SuspendThread(hMainThread)) { // error jl_safe_printf("error: SuspendThread failed\n"); return; } int force = jl_check_force_sigint(); if (force || (!ptls2->defer_signal && ptls2->io_wait)) { jl_safepoint_consume_sigint(); if (force) jl_safe_printf("WARNING: Force throwing a SIGINT\n"); // Force a throw jl_clear_force_sigint(); CONTEXT ctxThread; memset(&ctxThread, 0, sizeof(CONTEXT)); ctxThread.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; if (!GetThreadContext(hMainThread, &ctxThread)) { // error jl_safe_printf("error: GetThreadContext failed\n"); return; } jl_throw_in_ctx(jl_interrupt_exception, &ctxThread, 1); ctxThread.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; if (!SetThreadContext(hMainThread, &ctxThread)) { jl_safe_printf("error: SetThreadContext failed\n"); // error return; } } if ((DWORD)-1 == ResumeThread(hMainThread)) { jl_safe_printf("error: ResumeThread failed\n"); // error return; } }
// 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(); int errno_save = errno; sig_atomic_t request = jl_atomic_exchange(&ptls->signal_request, 0); #if !defined(JL_DISABLE_LIBUNWIND) 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 #endif if (request == 2) { 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, sig, ctx); } } else if (request == 3) { jl_call_in_ctx(ptls, jl_exit_thread0_cb, sig, ctx); } errno = errno_save; }