[runtime] Report crash when receiving crashing signals (#2052)
authormonojenkins <jo.shields+jenkins@xamarin.com>
Thu, 6 Feb 2020 00:05:02 +0000 (19:05 -0500)
committerGitHub <noreply@github.com>
Thu, 6 Feb 2020 00:05:02 +0000 (19:05 -0500)
The default handlers for SIGTRAP, SIGSYS on macOS and Linux crash the process, so we now have Mono report this.

This change also changes the presentation of the signal name on the stacktrace report dumped on error (from e.g. "SIGSEGV" to "segv").

Co-authored-by: Alexis Christoforides <alexis@thenull.net>
15 files changed:
src/mono/configure.ac
src/mono/mono/metadata/icall.c
src/mono/mono/mini/exceptions-amd64.c
src/mono/mono/mini/exceptions-ppc.c
src/mono/mono/mini/exceptions-x86.c
src/mono/mono/mini/mini-posix.c
src/mono/mono/mini/mini-runtime.c
src/mono/mono/mini/mini-runtime.h
src/mono/mono/mini/mini-windows.c
src/mono/mono/utils/Makefile.am
src/mono/mono/utils/mono-merp.c
src/mono/mono/utils/mono-signal-handler.c [new file with mode: 0644]
src/mono/mono/utils/mono-signal-handler.h
src/mono/msvc/libmonoutils-common.targets
src/mono/msvc/libmonoutils-common.targets.filters

index b9534be..f092a1e 100644 (file)
@@ -2937,6 +2937,23 @@ if test x$host_win32 = xno; then
        fi
 
        dnl ********************************
+       dnl *** Checks for sys_signame ***
+       dnl ********************************
+       AC_MSG_CHECKING(for sys_signame)
+               AC_TRY_LINK([
+               #include <signal.h>
+       ], [
+               const char *signame = sys_signame[0];
+       ], [
+               # Yes, we have it...
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_SYSSIGNAME, 1, [Have sys_signame])
+       ], [
+               AC_MSG_RESULT(no)
+       ])
+
+
+       dnl ********************************
        dnl *** Checks for semaphore lib ***
        dnl ********************************
        # 'Real Time' functions on Solaris
index 3ed967a..f0c67c1 100644 (file)
 #include "icall-decl.h"
 #include "mono/utils/mono-threads-coop.h"
 #include "mono/metadata/icall-signatures.h"
+#include "mono/utils/mono-signal-handler.h"
 
 //#define MONO_DEBUG_ICALLARRAY
 
@@ -6525,7 +6526,7 @@ ves_icall_Mono_Runtime_SendMicrosoftTelemetry (const char *payload, guint64 port
        hashes.offset_rich_hash = unportable_hash;
 
        // Tells mono that we want to send the HANG EXC_TYPE.
-       const char *signal = "SIGTERM";
+       const char *signal = mono_get_signame (SIGTERM);
 
        gboolean success = mono_merp_invoke (crashed_pid, signal, payload, &hashes);
        if (!success) {
index a551ea0..cd0397e 100644 (file)
@@ -66,7 +66,7 @@ static LONG CALLBACK seh_unhandled_exception_filter(EXCEPTION_POINTERS* ep)
 #endif
 
        if (mono_dump_start ())
-               mono_handle_native_crash ("SIGSEGV", NULL, NULL);
+               mono_handle_native_crash (mono_get_signame (SIGSEGV), NULL, NULL);
 
        return EXCEPTION_CONTINUE_SEARCH;
 }
@@ -876,7 +876,7 @@ altstack_handle_and_restore (MonoContext *ctx, MonoObject *obj, guint32 flags)
 
        if (!ji || (!stack_ovf && !nullref)) {
                if (mono_dump_start ())
-                       mono_handle_native_crash ("SIGSEGV", ctx, NULL);
+                       mono_handle_native_crash (mono_get_signame (SIGSEGV), ctx, NULL);
                // if couldn't dump or if mono_handle_native_crash returns, abort
                abort ();
        }
index d14f838..867dd1e 100644 (file)
@@ -676,7 +676,7 @@ mono_arch_handle_altstack_exception (void *sigctx, MONO_SIG_HANDLER_INFO_TYPE *s
        }
        if (!ji)
                if (mono_dump_start ())
-                       mono_handle_native_crash ("SIGSEGV", (MonoContext*)sigctx, siginfo);
+                       mono_handle_native_crash (mono_get_signame (SIGSEGV), (MonoContext*)sigctx, siginfo);
        /* setup a call frame on the real stack so that control is returned there
         * and exception handling can continue.
         * The frame looks like:
index 467a4bd..22e54bc 100644 (file)
@@ -67,7 +67,7 @@ static LONG CALLBACK seh_unhandled_exception_filter(EXCEPTION_POINTERS* ep)
        }
 #endif
        if (mono_dump_start ())
-               mono_handle_native_crash ("SIGSEGV", NULL, NULL);
+               mono_handle_native_crash (mono_get_signame (SIGSEGV), NULL, NULL);
 
        return EXCEPTION_CONTINUE_SEARCH;
 }
@@ -1140,7 +1140,7 @@ mono_arch_handle_altstack_exception (void *sigctx, MONO_SIG_HANDLER_INFO_TYPE *s
                MonoContext mctx;
                mono_sigctx_to_monoctx (sigctx, &mctx);
                if (mono_dump_start ())
-                       mono_handle_native_crash ("SIGSEGV", &mctx, siginfo);
+                       mono_handle_native_crash (mono_get_signame (SIGSEGV), &mctx, siginfo);
                else
                        abort ();
        }
index fd32733..2d11b56 100644 (file)
@@ -231,7 +231,7 @@ MONO_SIG_HANDLER_FUNC (static, sigabrt_signal_handler)
                        return;
                mono_sigctx_to_monoctx (ctx, &mctx);
                if (mono_dump_start ())
-                       mono_handle_native_crash ("SIGABRT", &mctx, info);
+                       mono_handle_native_crash (mono_get_signame (info->si_signo), &mctx, info);
                else
                        abort ();
        }
@@ -240,6 +240,7 @@ MONO_SIG_HANDLER_FUNC (static, sigabrt_signal_handler)
 MONO_SIG_HANDLER_FUNC (static, sigterm_signal_handler)
 {
 #ifndef DISABLE_CRASH_REPORTING
+       MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
        MONO_SIG_HANDLER_GET_CONTEXT;
 
        // Note: this is only run from the non-controlling thread
@@ -252,7 +253,7 @@ MONO_SIG_HANDLER_FUNC (static, sigterm_signal_handler)
        // running. Returns FALSE on unrecoverable error.
        if (mono_dump_start ()) {
                // Process was killed from outside since crash reporting wasn't running yet.
-               mono_handle_native_crash ("SIGTERM", &mctx, NULL);
+               mono_handle_native_crash (mono_get_signame (info->si_signo), &mctx, NULL);
        } else {
                // Crash reporting already running and we got a second SIGTERM from as part of thread-summarizing
                if (!mono_threads_summarize_execute (&mctx, &output, &hashes, FALSE, NULL, 0))
@@ -437,6 +438,7 @@ mono_runtime_posix_install_handlers (void)
 
        sigset_t signal_set;
        sigemptyset (&signal_set);
+       mono_load_signames ();
        if (mini_debug_options.handle_sigint) {
                add_signal_handler (SIGINT, mono_sigint_signal_handler, SA_RESTART);
                sigaddset (&signal_set, SIGINT);
@@ -446,7 +448,7 @@ mono_runtime_posix_install_handlers (void)
        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);
+       add_signal_handler (SIGILL, mono_crashing_signal_handler, 0);
        sigaddset (&signal_set, SIGILL);
        add_signal_handler (SIGBUS, mono_sigsegv_signal_handler, 0);
        sigaddset (&signal_set, SIGBUS);
@@ -454,6 +456,10 @@ mono_runtime_posix_install_handlers (void)
                add_signal_handler (SIGUSR2, sigusr2_signal_handler, SA_RESTART);
                sigaddset (&signal_set, SIGUSR2);
        }
+       add_signal_handler (SIGTRAP, mono_crashing_signal_handler, 0);
+       sigaddset (&signal_set, SIGTRAP);
+       add_signal_handler (SIGSYS, mono_crashing_signal_handler, 0);
+       sigaddset (&signal_set, SIGSYS);
 
        /* 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.
index a1ea121..c1b5925 100644 (file)
@@ -3227,7 +3227,7 @@ MONO_SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
 
                mono_sigctx_to_monoctx (ctx, &mctx);
                if (mono_dump_start ())
-                       mono_handle_native_crash ("SIGFPE", &mctx, info);
+                       mono_handle_native_crash (mono_get_signame (SIGFPE), &mctx, info);
                if (mono_do_crash_chaining) {
                        mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
                        goto exit;
@@ -3240,7 +3240,7 @@ exit:
        MONO_EXIT_GC_UNSAFE_UNBALANCED;
 }
 
-MONO_SIG_HANDLER_FUNC (, mono_sigill_signal_handler)
+MONO_SIG_HANDLER_FUNC (, mono_crashing_signal_handler)
 {
        MonoContext mctx;
        MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
@@ -3251,12 +3251,15 @@ MONO_SIG_HANDLER_FUNC (, mono_sigill_signal_handler)
 
        mono_sigctx_to_monoctx (ctx, &mctx);
        if (mono_dump_start ())
-               mono_handle_native_crash ("SIGILL", &mctx, info);
+#if defined(HAVE_SIG_INFO) && !defined(HOST_WIN32) // info is a siginfo_t
+               mono_handle_native_crash (mono_get_signame (info->si_signo), &mctx, info);
+#else
+               mono_handle_native_crash (mono_get_signame (SIGTERM), &mctx, info);
+#endif
        if (mono_do_crash_chaining) {
                mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
                return;
        }
-
 }
 
 #if defined(MONO_ARCH_USE_SIGACTION) || defined(HOST_WIN32)
@@ -3326,6 +3329,9 @@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
                mono_aot_handle_pagefault (info->si_addr);
                return;
        }
+       int signo = info->si_signo;
+#else
+       int signo = SIGSEGV;
 #endif
 
        /* The thread might no be registered with the runtime */
@@ -3333,7 +3339,7 @@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
                if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
                        return;
                if (mono_dump_start())
-                       mono_handle_native_crash ("SIGSEGV", &mctx, info);
+                       mono_handle_native_crash (mono_get_signame (signo), &mctx, info);
                if (mono_do_crash_chaining) {
                        mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
                        return;
@@ -3376,7 +3382,7 @@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
                } else {
                        // FIXME: This shouldn't run on the altstack
                        if (mono_dump_start ())
-                               mono_handle_native_crash ("SIGSEGV", &mctx, info);
+                               mono_handle_native_crash (mono_get_signame (SIGSEGV), &mctx, info);
                }
 #endif
        }
@@ -3387,7 +3393,7 @@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
                        return;
 
                if (mono_dump_start ())
-                       mono_handle_native_crash ("SIGSEGV", &mctx, (MONO_SIG_HANDLER_INFO_TYPE*)info);
+                       mono_handle_native_crash (mono_get_signame (SIGSEGV), &mctx, (MONO_SIG_HANDLER_INFO_TYPE*)info);
 
                if (mono_do_crash_chaining) {
                        mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
@@ -3399,7 +3405,7 @@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
                mono_arch_handle_exception (ctx, NULL);
        } else {
                if (mono_dump_start ())
-                       mono_handle_native_crash ("SIGSEGV", &mctx, (MONO_SIG_HANDLER_INFO_TYPE*)info);
+                       mono_handle_native_crash (mono_get_signame (SIGSEGV), &mctx, (MONO_SIG_HANDLER_INFO_TYPE*)info);
        }
 #endif
 }
index b7dc805..e2fd25a 100644 (file)
@@ -571,7 +571,7 @@ mono_is_addr_implicit_null_check (void *addr);
 #endif
 
 void MONO_SIG_HANDLER_SIGNATURE (mono_sigfpe_signal_handler) ;
-void MONO_SIG_HANDLER_SIGNATURE (mono_sigill_signal_handler) ;
+void MONO_SIG_HANDLER_SIGNATURE (mono_crashing_signal_handler) ;
 void MONO_SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler);
 void MONO_SIG_HANDLER_SIGNATURE (mono_sigint_signal_handler) ;
 gboolean MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal);
index 6a02867..673aeef 100644 (file)
@@ -193,7 +193,7 @@ mono_runtime_install_handlers (void)
 #ifndef MONO_CROSS_COMPILE
        win32_seh_init();
        win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
-       win32_seh_set_handler(SIGILL, mono_sigill_signal_handler);
+       win32_seh_set_handler(SIGILL, mono_crashing_signal_handler);
        win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
        if (mini_debug_options.handle_sigint)
                win32_seh_set_handler(SIGINT, mono_sigint_signal_handler);
index 07befc3..110065d 100644 (file)
@@ -206,6 +206,7 @@ monoutils_sources = \
        bsearch.h       \
        bsearch.c       \
        mono-signal-handler.h   \
+       mono-signal-handler.c   \
        mono-conc-hashtable.h   \
        mono-conc-hashtable.c   \
        json.h  \
index f12438c..cf78dbf 100644 (file)
@@ -40,6 +40,7 @@
 #include <mono/utils/json.h>
 #include <mono/utils/mono-state.h>
 #include <utils/mono-threads-debug.h>
+#include <utils/mono-signal-handler.h>
 
 static const char *
 kernel_version_string (void)
@@ -272,21 +273,27 @@ get_merp_exctype (MERPExcType exc)
 static MERPExcType
 parse_exception_type (const char *signal)
 {
-       if (!strcmp (signal, "SIGSEGV"))
+       if (!strcmp (signal, mono_get_signame (SIGSEGV)))
                return MERP_EXC_SIGSEGV;
 
-       if (!strcmp (signal, "SIGFPE"))
+       if (!strcmp (signal, mono_get_signame (SIGFPE)))
                return MERP_EXC_SIGFPE;
 
-       if (!strcmp (signal, "SIGILL"))
+       if (!strcmp (signal, mono_get_signame (SIGILL)))
                return MERP_EXC_SIGILL;
 
-       if (!strcmp (signal, "SIGABRT"))
+       if (!strcmp (signal, mono_get_signame (SIGABRT)))
                return MERP_EXC_SIGABRT;
 
+       if (!strcmp (signal, mono_get_signame (SIGTRAP)))
+               return MERP_EXC_SIGTRAP;
+
+       if (!strcmp (signal, mono_get_signame (SIGSYS)))
+               return MERP_EXC_SIGSYS;
+
        // Force quit == hang?
        // We need a default for this
-       if (!strcmp (signal, "SIGTERM"))
+       if (!strcmp (signal, mono_get_signame (SIGTERM)))
                return MERP_EXC_HANG;
 
        // FIXME: There are no other such signal
diff --git a/src/mono/mono/utils/mono-signal-handler.c b/src/mono/mono/utils/mono-signal-handler.c
new file mode 100644 (file)
index 0000000..8f0d648
--- /dev/null
@@ -0,0 +1,78 @@
+#include "config.h"
+#include <signal.h>
+#include <string.h>
+#include "mono/utils/mono-signal-handler.h"
+
+struct mono_sigpair
+{
+       int signo;
+       const char* signame;
+};
+
+#if !defined (HAVE_SYSSIGNAME)
+static struct mono_sigpair mono_signames[] =
+{
+       {SIGABRT, "SIGABRT"},
+#if defined (SIGKILL)
+       {SIGKILL, "SIGKILL"},
+#endif
+#if defined (SIGTRAP)
+       {SIGTRAP, "SIGTRAP"},
+#endif
+#if defined (SIGSYS)
+       {SIGSYS, "SIGSYS"},
+#endif
+       {SIGSEGV, "SIGSEGV"},
+#if defined (SIGQUIT)
+       {SIGQUIT, "SIGQUIT"},
+#endif
+       {SIGFPE, "SIGFPE"},
+       {SIGILL, "SIGILL"},
+#if defined (SIGBUS)
+       {SIGBUS, "SIGBUS"} // How come this is seems not available on Android, but is used unconditionally in mini-posix.c:mono_runtime_posix_install_handlers ?
+#endif
+};
+#endif
+
+static struct mono_sigpair *sigpair_buf;
+static int sigpair_buflen;
+
+void
+mono_load_signames ()
+{
+       if (sigpair_buf)
+               return;
+#if defined (HAVE_SYSSIGNAME)
+       sigpair_buflen = sizeof (sys_signame) / sizeof (sys_signame [0]);
+       sigpair_buf = (struct mono_sigpair *) g_malloc (sigpair_buflen * sizeof (struct mono_sigpair));
+       struct mono_sigpair *cur = sigpair_buf;
+       for (int i = 0; i < sigpair_buflen; ++i)
+       {
+               cur->signo = i;
+               cur->signame = sys_signame [i];
+               cur++;
+       }
+
+#else
+       sigpair_buflen = sizeof (mono_signames) / sizeof (mono_signames [0]);
+       sigpair_buf = mono_signames;
+#endif
+
+}
+
+const char *
+mono_get_signame (int signo)
+{
+       const char *result = "UNKNOWN";
+       struct mono_sigpair *cur = sigpair_buf;
+       for (int i = 0; i < sigpair_buflen; ++i)
+       {
+               if (cur->signo == signo)
+               {
+                       result = cur->signame;
+                       break;
+               }
+               cur++;
+       }
+       return result;
+}
index 80ea049..0b2b384 100644 (file)
@@ -10,6 +10,7 @@
 #define __MONO_SIGNAL_HANDLER_H__
 
 #include "config.h"
+#include <glib.h>
 
 /*
  * When a signal is delivered to a thread on a Krait Android device
@@ -78,6 +79,7 @@
  */
 
 #ifdef HOST_WIN32
+#include <windows.h>
 #define MONO_SIG_HANDLER_INFO_TYPE MonoWindowsSigHandlerInfo
 typedef struct {
        /* Set to FALSE to indicate chained signal handler needs run.
@@ -99,4 +101,7 @@ typedef struct {
 #define MONO_SIG_HANDLER_GET_INFO() (_info)
 #define MONO_SIG_HANDLER_GET_CONTEXT void *ctx = context;
 
+void mono_load_signames (void);
+const char * mono_get_signame (int signo);
+
 #endif // __MONO_SIGNAL_HANDLER_H__
index 210c41e..8c39996 100644 (file)
     <ClInclude Include="$(MonoSourceLocation)\mono\utils\bsearch.h" />
     <ClCompile Include="$(MonoSourceLocation)\mono\utils\bsearch.c" />
     <ClInclude Include="$(MonoSourceLocation)\mono\utils\mono-signal-handler.h" />
+    <ClCompile Include="$(MonoSourceLocation)\mono\utils\mono-signal-handler.c" />
     <ClInclude Include="$(MonoSourceLocation)\mono\utils\mono-conc-hashtable.h" />
     <ClCompile Include="$(MonoSourceLocation)\mono\utils\mono-conc-hashtable.c" />
     <ClInclude Include="$(MonoSourceLocation)\mono\utils\json.h" />
index 9c26c4a..0c00124 100644 (file)
     <ClInclude Include="$(MonoSourceLocation)\mono\utils\mono-signal-handler.h">
       <Filter>Header Files$(MonoUtilsFilterSubFolder)\common</Filter>
     </ClInclude>
+    <ClCompile Include="$(MonoSourceLocation)\mono\utils\mono-signal-handler.c">
+      <Filter>Source Files$(MonoUtilsFilterSubFolder)\common</Filter>
+    </ClCompile>
     <ClInclude Include="$(MonoSourceLocation)\mono\utils\mono-conc-hashtable.h">
       <Filter>Header Files$(MonoUtilsFilterSubFolder)\common</Filter>
     </ClInclude>