From 8c941a5229f5b03f38e00fca1f916bcf1c5050ab Mon Sep 17 00:00:00 2001 From: monojenkins Date: Wed, 5 Feb 2020 19:05:02 -0500 Subject: [PATCH] [runtime] Report crash when receiving crashing signals (#2052) 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 --- 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 b9534be6122c0..f092a1e583432 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 3ed967ade1028..f0c67c192d295 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 a551ea0cabc1c..cd0397ef39ed2 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 d14f8383eba91..867dd1eae0f83 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 467a4bda47cf9..22e54bc9258a5 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 fd32733317bb8..2d11b566a4513 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 a1ea1215a9d5b..c1b5925b2edb9 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -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 @@ 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 (); @@ -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 } diff --git a/src/mono/mono/mini/mini-runtime.h b/src/mono/mono/mini/mini-runtime.h index b7dc8054c1d92..e2fd25ae4d776 100644 --- a/src/mono/mono/mini/mini-runtime.h +++ b/src/mono/mono/mini/mini-runtime.h @@ -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); diff --git a/src/mono/mono/mini/mini-windows.c b/src/mono/mono/mini/mini-windows.c index 6a02867da6de3..673aeefeeede3 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 07befc3503d43..110065d4f818d 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 f12438c03e671..cf78dbf63d4e6 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 0000000000000..8f0d6481bee6a --- /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 80ea049239a3d..0b2b38482b257 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 210c41e049352..8c39996b1c621 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 9c26c4a93e2e1..0c00124958b68 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