[corlib] Add API to uninstall/reinstall signal handlers.
authorRolf Bjarne Kvinge <rolf@xamarin.com>
Fri, 23 Sep 2016 11:53:36 +0000 (13:53 +0200)
committerRolf Bjarne Kvinge <rolf@xamarin.com>
Tue, 27 Sep 2016 10:35:14 +0000 (12:35 +0200)
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
mono/mini/mini-posix.c
mono/mini/mini-runtime.c

index 7a5f9887c6334fff01b0f7f9835659b44fac9be3..efac37b709affdcf88a28ff4184b3d07043f777d 100644 (file)
@@ -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
index e192403487b04d4571351f9551a91bac3e4e065f..b0d7a0709db70da65da166e78c821cdd66b50743 100644 (file)
@@ -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;
index a9c87011153b35ba64bf2d25f057801ea21ee03a..addb26bd446c5ad029797d2014b9ee49db71d602 100644 (file)
@@ -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",