From 59b6fde1b375e82de1a62ee772c1808cd379a53c Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 23 Sep 2016 13:53:36 +0200 Subject: [PATCH] [corlib] Add API to uninstall/reinstall signal handlers. This API is provided to be used by libraries providing crash reporting, so that those libraries can install signal handlers and at the same time not interfere with Mono's signals. The intended pattern is this: Mono.Runtime.RemoveSignalHandlers (); InstallThirdPartySignalHandlers (); Mono.Runtime.InstallSignalHandlers (); This ensures that Mono is always notified first of any signals, and will then chain to the third-party signal handlers if the signal did not originate in managed code. Mono's signals must first be removed, so that if third-party signal handler does signal chaining, we don't end up in Mono's signal handler again. Mailing-list thread: http://lists.dot.net/pipermail/macios-devel/2016-September/000016.html [Signal-chaining & crash reporters] Example usage: https://github.com/rolfbjarne/HockeySDK-Xamarin/commit/862721199f1adec210bfc7b1943f975ffb8048a9 --- mcs/class/corlib/Mono/Runtime.cs | 17 ++++++++++++++++- mono/mini/mini-posix.c | 14 +++++++++----- mono/mini/mini-runtime.c | 2 ++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/mcs/class/corlib/Mono/Runtime.cs b/mcs/class/corlib/Mono/Runtime.cs index 7a5f9887c63..efac37b709a 100644 --- a/mcs/class/corlib/Mono/Runtime.cs +++ b/mcs/class/corlib/Mono/Runtime.cs @@ -40,11 +40,26 @@ namespace Mono { [MethodImplAttribute (MethodImplOptions.InternalCall)] private static extern void mono_runtime_install_handlers (); - static internal void InstallSignalHandlers () +#if MOBILE + public +#else + internal +#endif + static void InstallSignalHandlers () { mono_runtime_install_handlers (); } +#if MOBILE + [MethodImplAttribute (MethodImplOptions.InternalCall)] + static extern void mono_runtime_cleanup_handlers (); + + public static void RemoveSignalHandlers () + { + mono_runtime_cleanup_handlers (); + } +#endif + // Should not be removed intended for external use // Safe to be called using reflection // Format is undefined only for use as a string for reporting diff --git a/mono/mini/mini-posix.c b/mono/mini/mini-posix.c index e192403487b..b0d7a0709db 100644 --- a/mono/mini/mini-posix.c +++ b/mono/mini/mini-posix.c @@ -140,11 +140,15 @@ mono_gdb_render_native_backtraces (pid_t crashed_pid) static GHashTable *mono_saved_signal_handlers = NULL; static struct sigaction * -get_saved_signal_handler (int signo) +get_saved_signal_handler (int signo, gboolean remove) { - if (mono_saved_signal_handlers) + if (mono_saved_signal_handlers) { /* The hash is only modified during startup, so no need for locking */ - return (struct sigaction *)g_hash_table_lookup (mono_saved_signal_handlers, GINT_TO_POINTER (signo)); + struct sigaction *handler = g_hash_table_lookup (mono_saved_signal_handlers, GINT_TO_POINTER (signo)); + if (remove && handler) + g_hash_table_remove (mono_saved_signal_handlers, GINT_TO_POINTER (signo)); + return handler; + } return NULL; } @@ -191,7 +195,7 @@ gboolean MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal) { int signal = MONO_SIG_HANDLER_GET_SIGNO (); - struct sigaction *saved_handler = (struct sigaction *)get_saved_signal_handler (signal); + struct sigaction *saved_handler = (struct sigaction *)get_saved_signal_handler (signal, FALSE); if (saved_handler && saved_handler->sa_handler) { if (!(saved_handler->sa_flags & SA_SIGINFO)) { @@ -446,7 +450,7 @@ static void remove_signal_handler (int signo) { struct sigaction sa; - struct sigaction *saved_action = get_saved_signal_handler (signo); + struct sigaction *saved_action = get_saved_signal_handler (signo, TRUE); if (!saved_action) { sa.sa_handler = SIG_DFL; diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c index a9c87011153..addb26bd446 100644 --- a/mono/mini/mini-runtime.c +++ b/mono/mini/mini-runtime.c @@ -3744,6 +3744,8 @@ register_icalls (void) ves_icall_get_trace); mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers", mono_runtime_install_handlers); + mono_add_internal_call ("Mono.Runtime::mono_runtime_cleanup_handlers", + mono_runtime_cleanup_handlers); #if defined(PLATFORM_ANDROID) || defined(TARGET_ANDROID) mono_add_internal_call ("System.Diagnostics.Debugger::Mono_UnhandledException_internal", -- 2.11.4.GIT