void mono_runtime_posix_install_handlers (void) { sigset_t signal_set; sigemptyset (&signal_set); if (mini_get_debug_options ()->handle_sigint) { add_signal_handler (SIGINT, mono_sigint_signal_handler, SA_RESTART); sigaddset (&signal_set, SIGINT); } add_signal_handler (SIGFPE, mono_sigfpe_signal_handler, 0); sigaddset (&signal_set, SIGFPE); add_signal_handler (SIGQUIT, sigquit_signal_handler, SA_RESTART); sigaddset (&signal_set, SIGQUIT); add_signal_handler (SIGILL, mono_sigill_signal_handler, 0); sigaddset (&signal_set, SIGILL); add_signal_handler (SIGBUS, mono_sigsegv_signal_handler, 0); sigaddset (&signal_set, SIGBUS); if (mono_jit_trace_calls != NULL) { add_signal_handler (SIGUSR2, sigusr2_signal_handler, SA_RESTART); sigaddset (&signal_set, SIGUSR2); } /* 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. */ if (mono_gc_get_suspend_signal () != -1) sigaddset (&signal_set, mono_gc_get_suspend_signal ()); if (mono_gc_get_restart_signal () != -1) sigaddset (&signal_set, mono_gc_get_restart_signal ()); sigaddset (&signal_set, SIGCHLD); signal (SIGPIPE, SIG_IGN); sigaddset (&signal_set, SIGPIPE); add_signal_handler (SIGABRT, sigabrt_signal_handler, 0); sigaddset (&signal_set, SIGABRT); /* catch SIGSEGV */ add_signal_handler (SIGSEGV, mono_sigsegv_signal_handler, 0); sigaddset (&signal_set, SIGSEGV); sigprocmask (SIG_UNBLOCK, &signal_set, NULL); }
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 ()); if (mono_gc_get_suspend_signal () != -1) sigaddset (&signal_set, mono_gc_get_suspend_signal ()); if (mono_gc_get_restart_signal () != -1) sigaddset (&signal_set, mono_gc_get_restart_signal ()); sigaddset (&signal_set, SIGCHLD); 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); }