From 635a99094b545a7ae552ba833a9a1c875acb821c Mon Sep 17 00:00:00 2001 From: alexischr Date: Mon, 3 Feb 2020 14:19:46 +0000 Subject: [PATCH] [runtime] Report crash when receiving crashing signals 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"). --- src/mono/configure.ac | 17 ++++ src/mono/mono/metadata/icall.c | 3 +- src/mono/mono/mini/exceptions-amd64.c | 4 +- src/mono/mono/mini/exceptions-ppc.c | 2 +- src/mono/mono/mini/exceptions-x86.c | 4 +- src/mono/mono/mini/mini-posix.c | 12 ++- src/mono/mono/mini/mini-runtime.c | 22 ++++-- src/mono/mono/mini/mini-runtime.h | 2 +- src/mono/mono/mini/mini-windows.c | 2 +- src/mono/mono/utils/Makefile.am | 1 + src/mono/mono/utils/mono-merp.c | 17 ++-- src/mono/mono/utils/mono-signal-handler.c | 78 +++++++++++++++++++ src/mono/mono/utils/mono-signal-handler.h | 5 ++ src/mono/msvc/libmonoutils-common.targets | 1 + .../msvc/libmonoutils-common.targets.filters | 3 + 15 files changed, 149 insertions(+), 24 deletions(-) create mode 100644 src/mono/mono/utils/mono-signal-handler.c diff --git a/src/mono/configure.ac b/src/mono/configure.ac index df94e2d25b8fd2..09e3192852c8fa 100644 --- a/src/mono/configure.ac +++ b/src/mono/configure.ac @@ -2936,6 +2936,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 + ], [ + 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 ******************************** diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index e3357c03f7ee0e..bfb217dceb40eb 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -118,6 +118,7 @@ #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) { diff --git a/src/mono/mono/mini/exceptions-amd64.c b/src/mono/mono/mini/exceptions-amd64.c index a551ea0cabc1cc..cd0397ef39ed24 100644 --- a/src/mono/mono/mini/exceptions-amd64.c +++ b/src/mono/mono/mini/exceptions-amd64.c @@ -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 (); } diff --git a/src/mono/mono/mini/exceptions-ppc.c b/src/mono/mono/mini/exceptions-ppc.c index d14f8383eba915..867dd1eae0f832 100644 --- a/src/mono/mono/mini/exceptions-ppc.c +++ b/src/mono/mono/mini/exceptions-ppc.c @@ -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: diff --git a/src/mono/mono/mini/exceptions-x86.c b/src/mono/mono/mini/exceptions-x86.c index 467a4bda47cf98..22e54bc9258a51 100644 --- a/src/mono/mono/mini/exceptions-x86.c +++ b/src/mono/mono/mini/exceptions-x86.c @@ -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 (); } diff --git a/src/mono/mono/mini/mini-posix.c b/src/mono/mono/mini/mini-posix.c index fd32733317bb80..2d11b566a4513e 100644 --- a/src/mono/mono/mini/mini-posix.c +++ b/src/mono/mono/mini/mini-posix.c @@ -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. diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 6b4d396c9d9e6c..456568b179bd7f 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -3226,7 +3226,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; @@ -3239,7 +3239,7 @@ MONO_SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler) 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 (); @@ -3250,12 +3250,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) @@ -3325,6 +3328,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 */ @@ -3332,7 +3338,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; @@ -3375,7 +3381,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 } @@ -3386,7 +3392,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); @@ -3398,7 +3404,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 } diff --git a/src/mono/mono/mini/mini-runtime.h b/src/mono/mono/mini/mini-runtime.h index 91b80ab1e911a5..43b12ac63f7051 100644 --- a/src/mono/mono/mini/mini-runtime.h +++ b/src/mono/mono/mini/mini-runtime.h @@ -569,7 +569,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); diff --git a/src/mono/mono/mini/mini-windows.c b/src/mono/mono/mini/mini-windows.c index 6a02867da6de32..673aeefeeede3b 100644 --- a/src/mono/mono/mini/mini-windows.c +++ b/src/mono/mono/mini/mini-windows.c @@ -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); diff --git a/src/mono/mono/utils/Makefile.am b/src/mono/mono/utils/Makefile.am index 07befc3503d431..110065d4f818de 100644 --- a/src/mono/mono/utils/Makefile.am +++ b/src/mono/mono/utils/Makefile.am @@ -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 \ diff --git a/src/mono/mono/utils/mono-merp.c b/src/mono/mono/utils/mono-merp.c index f12438c03e6712..cf78dbf63d4e60 100644 --- a/src/mono/mono/utils/mono-merp.c +++ b/src/mono/mono/utils/mono-merp.c @@ -40,6 +40,7 @@ #include #include #include +#include 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 index 00000000000000..8f0d6481bee6a0 --- /dev/null +++ b/src/mono/mono/utils/mono-signal-handler.c @@ -0,0 +1,78 @@ +#include "config.h" +#include +#include +#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; +} diff --git a/src/mono/mono/utils/mono-signal-handler.h b/src/mono/mono/utils/mono-signal-handler.h index 80ea049239a3db..0b2b38482b2570 100644 --- a/src/mono/mono/utils/mono-signal-handler.h +++ b/src/mono/mono/utils/mono-signal-handler.h @@ -10,6 +10,7 @@ #define __MONO_SIGNAL_HANDLER_H__ #include "config.h" +#include /* * When a signal is delivered to a thread on a Krait Android device @@ -78,6 +79,7 @@ */ #ifdef HOST_WIN32 +#include #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__ diff --git a/src/mono/msvc/libmonoutils-common.targets b/src/mono/msvc/libmonoutils-common.targets index 210c41e0493524..8c39996b1c621e 100644 --- a/src/mono/msvc/libmonoutils-common.targets +++ b/src/mono/msvc/libmonoutils-common.targets @@ -174,6 +174,7 @@ + diff --git a/src/mono/msvc/libmonoutils-common.targets.filters b/src/mono/msvc/libmonoutils-common.targets.filters index 9c26c4a93e2e13..0c00124958b689 100644 --- a/src/mono/msvc/libmonoutils-common.targets.filters +++ b/src/mono/msvc/libmonoutils-common.targets.filters @@ -403,6 +403,9 @@ Header Files$(MonoUtilsFilterSubFolder)\common + + Source Files$(MonoUtilsFilterSubFolder)\common + Header Files$(MonoUtilsFilterSubFolder)\common