Esempio n. 1
0
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);
}
Esempio n. 2
0
void
mono_threads_posix_init_signals (MonoThreadPosixInitSignals signals)
{
	sigset_t signal_set;

	g_assert ((signals == MONO_THREADS_POSIX_INIT_SIGNALS_SUSPEND_RESTART) ^ (signals == MONO_THREADS_POSIX_INIT_SIGNALS_ABORT));

	sigemptyset (&signal_set);

	switch (signals) {
	case MONO_THREADS_POSIX_INIT_SIGNALS_SUSPEND_RESTART: {
		if (mono_thread_info_unified_management_enabled ()) {
			suspend_signal_num = DEFAULT_SUSPEND_SIGNAL;
			restart_signal_num = DEFAULT_RESTART_SIGNAL;
		} else {
			suspend_signal_num = suspend_signal_get ();
			restart_signal_num = restart_signal_get ();
		}

		sigfillset (&suspend_signal_mask);
		sigdelset (&suspend_signal_mask, restart_signal_num);
		if (!mono_thread_info_unified_management_enabled ())
			sigdelset (&suspend_signal_mask, mono_gc_get_suspend_signal ());

		sigemptyset (&suspend_ack_signal_mask);
		sigaddset (&suspend_ack_signal_mask, restart_signal_num);

		signal_add_handler (suspend_signal_num, suspend_signal_handler, SA_RESTART);
		signal_add_handler (restart_signal_num, restart_signal_handler, SA_RESTART);

		sigaddset (&signal_set, suspend_signal_num);
		sigaddset (&signal_set, restart_signal_num);

		break;
	}
	case MONO_THREADS_POSIX_INIT_SIGNALS_ABORT: {
		abort_signal_num = abort_signal_get ();

		signal_add_handler (abort_signal_num, abort_signal_handler, 0);

		sigaddset (&signal_set, abort_signal_num);

		break;
	}
	default: g_assert_not_reached ();
	}

	/* ensure all the new signals are unblocked */
	sigprocmask (SIG_UNBLOCK, &signal_set, NULL);
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
static void
add_signal_handler (int signo, gpointer handler, int flags)
{
	struct sigaction sa;
	struct sigaction previous_sa;

#ifdef MONO_ARCH_USE_SIGACTION
	sa.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler;
	sigemptyset (&sa.sa_mask);
	sa.sa_flags = SA_SIGINFO | flags;
#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK

/*Apple likes to deliver SIGBUS for *0 */
#ifdef HOST_DARWIN
	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);
	}
#else
	sa.sa_handler = handler;
	sigemptyset (&sa.sa_mask);
	sa.sa_flags = flags;
#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, TRUE);

	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);
	}
}

#ifdef TARGET_OSX
void
mini_register_sigterm_handler (void)
{
	/* always catch SIGTERM, conditionals inside of handler */
	add_signal_handler (SIGTERM, sigterm_signal_handler, 0);
}