gboolean mono_threads_core_suspend (MonoThreadInfo *info) { /*FIXME, check return value*/ mono_threads_pthread_kill (info, mono_thread_get_abort_signal ()); while (MONO_SEM_WAIT (&info->begin_suspend_semaphore) != 0) { /* g_assert (errno == EINTR); */ } return info->suspend_can_continue; }
void mono_threads_core_abort_syscall (MonoThreadInfo *info) { /* We signal a thread to break it from the urrent syscall. This signal should not be interpreted as a suspend request. */ info->syscall_break_signal = TRUE; mono_threads_pthread_kill (info, mono_thread_get_abort_signal ()); }
void mono_threads_init_platform (void) { #if !defined(__native_client__) /* FIXME we should use all macros from mini to make this more portable FIXME it would be very sweet if sgen could end up using this too. */ if (mono_thread_info_new_interrupt_enabled ()) mono_posix_add_signal_handler (mono_thread_get_abort_signal (), suspend_signal_handler); #endif }
void mono_runtime_cleanup_handlers (void) { if (mini_get_debug_options ()->handle_sigint) remove_signal_handler (SIGINT); remove_signal_handler (SIGFPE); remove_signal_handler (SIGQUIT); remove_signal_handler (SIGILL); remove_signal_handler (SIGBUS); if (mono_jit_trace_calls != NULL) remove_signal_handler (SIGUSR2); remove_signal_handler (mono_thread_get_abort_signal ()); remove_signal_handler (SIGABRT); remove_signal_handler (SIGSEGV); free_saved_signal_handlers (); }
static void add_signal_handler (int signo, gpointer handler) { struct sigaction sa; struct sigaction previous_sa; #ifdef MONO_ARCH_USE_SIGACTION sa.sa_sigaction = handler; sigemptyset (&sa.sa_mask); sa.sa_flags = SA_SIGINFO; #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK /*Apple likes to deliver SIGBUS for *0 */ #ifdef __APPLE__ if (signo == SIGSEGV || signo == SIGBUS) { #else if (signo == SIGSEGV) { #endif sa.sa_flags |= SA_ONSTACK; /* * libgc will crash when trying to do stack marking for threads which are on * an altstack, so delay the suspend signal after the signal handler has * executed. */ if (mono_gc_get_suspend_signal () != -1) sigaddset (&sa.sa_mask, mono_gc_get_suspend_signal ()); } #endif if (signo == SIGSEGV) { /* * Delay abort signals while handling SIGSEGVs since they could go unnoticed. */ sigset_t block_mask; sigemptyset (&block_mask); sigaddset (&sa.sa_mask, mono_thread_get_abort_signal ()); } #else sa.sa_handler = handler; sigemptyset (&sa.sa_mask); sa.sa_flags = 0; #endif g_assert (sigaction (signo, &sa, &previous_sa) != -1); /* if there was already a handler in place for this signal, store it */ if (! (previous_sa.sa_flags & SA_SIGINFO) && (SIG_DFL == previous_sa.sa_handler)) { /* it there is no sa_sigaction function and the sa_handler is default, we can safely ignore this */ } else { if (mono_do_signal_chaining) save_old_signal_handler (signo, &previous_sa); } } static void remove_signal_handler (int signo) { struct sigaction sa; struct sigaction *saved_action = get_saved_signal_handler (signo); if (!saved_action) { sa.sa_handler = SIG_DFL; sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sigaction (signo, &sa, NULL); } else { g_assert (sigaction (signo, saved_action, NULL) != -1); } } void mono_runtime_posix_install_handlers (void) { sigset_t signal_set; if (mini_get_debug_options ()->handle_sigint) add_signal_handler (SIGINT, mono_sigint_signal_handler); add_signal_handler (SIGFPE, mono_sigfpe_signal_handler); add_signal_handler (SIGQUIT, sigquit_signal_handler); add_signal_handler (SIGILL, mono_sigill_signal_handler); add_signal_handler (SIGBUS, mono_sigsegv_signal_handler); if (mono_jit_trace_calls != NULL) add_signal_handler (SIGUSR2, sigusr2_signal_handler); if (!mono_thread_info_new_interrupt_enabled ()) add_signal_handler (mono_thread_get_abort_signal (), sigusr1_signal_handler); /* it seems to have become a common bug for some programs that run as parents * of many processes to block signal delivery for real time signals. * We try to detect and work around their breakage here. */ sigemptyset (&signal_set); sigaddset (&signal_set, mono_thread_get_abort_signal ()); sigprocmask (SIG_UNBLOCK, &signal_set, NULL); signal (SIGPIPE, SIG_IGN); add_signal_handler (SIGABRT, sigabrt_signal_handler); /* catch SIGSEGV */ add_signal_handler (SIGSEGV, mono_sigsegv_signal_handler); }