From db568c6fe0cb5eab71ed729ec5b412365eacf280 Mon Sep 17 00:00:00 2001 From: Alexis Christoforides Date: Sat, 26 Oct 2019 18:48:40 -0400 Subject: [PATCH] [merp] Introduce a new 'dump mode' that allows different signal behavior when dumping (#17537) * dump_native_stacktrace should always register the sigterm handler. Cherry picked from the https://github.com/mono/mono/pull/17310 * [merp] Introduce a new 'dump mode' that allows different signal behavior when dumping The primary reason for this is gaining the ability to interpret SIGTERM properly as a crashing signal when outside of 'dump mode', and as a utility signal during the 'thread summarizer' dumping process. --- mono/metadata/icall.c | 5 +++++ mono/mini/exceptions-amd64.c | 12 +++++++++--- mono/mini/exceptions-ppc.c | 4 +++- mono/mini/exceptions-x86.c | 10 +++++++--- mono/mini/mini-posix.c | 23 ++++++++++++++++------- mono/mini/mini-runtime.c | 19 +++++++++++++------ mono/utils/mono-state.c | 20 ++++++++++++++++++-- mono/utils/mono-state.h | 8 ++++++++ msvc/libmonoutils-common.targets | 2 ++ msvc/libmonoutils-common.targets.filters | 6 ++++++ 10 files changed, 87 insertions(+), 22 deletions(-) diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index daca2a95968..4ea18a5d450 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -6556,6 +6556,9 @@ ves_icall_Mono_Runtime_DumpStateTotal (guint64 *portable_hash, guint64 *unportab memset (&hashes, 0, sizeof (MonoStackHash)); MonoContext *ctx = NULL; + while (!mono_dump_start ()) + g_usleep (1000); // wait around for other dump to finish + mono_get_runtime_callbacks ()->install_state_summarizer (); mono_summarize_timeline_start (); @@ -6574,6 +6577,8 @@ ves_icall_Mono_Runtime_DumpStateTotal (guint64 *portable_hash, guint64 *unportab g_free (scratch); mono_summarize_timeline_phase_log (MonoSummaryDone); + + mono_dump_complete (); #else *portable_hash = 0; *unportable_hash = 0; diff --git a/mono/mini/exceptions-amd64.c b/mono/mini/exceptions-amd64.c index 88224bd5c76..636707e3ebf 100644 --- a/mono/mini/exceptions-amd64.c +++ b/mono/mini/exceptions-amd64.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "mini.h" #include "mini-amd64.h" @@ -63,7 +64,8 @@ static LONG CALLBACK seh_unhandled_exception_filter(EXCEPTION_POINTERS* ep) } #endif - mono_handle_native_crash ("SIGSEGV", NULL, NULL); + if (mono_dump_start ()) + mono_handle_native_crash ("SIGSEGV", NULL, NULL); return EXCEPTION_CONTINUE_SEARCH; } @@ -871,8 +873,12 @@ altstack_handle_and_restore (MonoContext *ctx, MonoObject *obj, guint32 flags) gboolean stack_ovf = (flags & 1) != 0; gboolean nullref = (flags & 2) != 0; - if (!ji || (!stack_ovf && !nullref)) - mono_handle_native_crash ("SIGSEGV", ctx, NULL); + if (!ji || (!stack_ovf && !nullref)) { + if (mono_dump_start ()) + mono_handle_native_crash ("SIGSEGV", ctx, NULL); + // if couldn't dump or if mono_handle_native_crash returns, abort + abort (); + } mctx = *ctx; diff --git a/mono/mini/exceptions-ppc.c b/mono/mini/exceptions-ppc.c index fc55044df7f..c251ccdb65d 100644 --- a/mono/mini/exceptions-ppc.c +++ b/mono/mini/exceptions-ppc.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "mini.h" #include "mini-ppc.h" @@ -673,7 +674,8 @@ mono_arch_handle_altstack_exception (void *sigctx, MONO_SIG_HANDLER_INFO_TYPE *s abort (); } if (!ji) - mono_handle_native_crash ("SIGSEGV", sigctx, siginfo); + if (mono_dump_start ()) + mono_handle_native_crash ("SIGSEGV", 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/mono/mini/exceptions-x86.c b/mono/mini/exceptions-x86.c index a55402b98d3..68e406f4a1d 100644 --- a/mono/mini/exceptions-x86.c +++ b/mono/mini/exceptions-x86.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "mini.h" #include "mini-x86.h" @@ -64,8 +65,8 @@ static LONG CALLBACK seh_unhandled_exception_filter(EXCEPTION_POINTERS* ep) return (*mono_old_win_toplevel_exception_filter)(ep); } #endif - - mono_handle_native_crash ("SIGSEGV", NULL, NULL); + if (mono_dump_start ()) + mono_handle_native_crash ("SIGSEGV", NULL, NULL); return EXCEPTION_CONTINUE_SEARCH; } @@ -1137,7 +1138,10 @@ mono_arch_handle_altstack_exception (void *sigctx, MONO_SIG_HANDLER_INFO_TYPE *s if (!ji) { MonoContext mctx; mono_sigctx_to_monoctx (sigctx, &mctx); - mono_handle_native_crash ("SIGSEGV", &mctx, siginfo); + if (mono_dump_start ()) + mono_handle_native_crash ("SIGSEGV", &mctx, siginfo); + else + abort (); } /* setup a call frame on the real stack so that control is returned there * and exception handling can continue. diff --git a/mono/mini/mini-posix.c b/mono/mini/mini-posix.c index 0f86b292770..7122baada3c 100644 --- a/mono/mini/mini-posix.c +++ b/mono/mini/mini-posix.c @@ -229,7 +229,10 @@ MONO_SIG_HANDLER_FUNC (static, sigabrt_signal_handler) if (mono_chain_signal (MONO_SIG_HANDLER_PARAMS)) return; mono_sigctx_to_monoctx (ctx, &mctx); - mono_handle_native_crash ("SIGABRT", &mctx, info); + if (mono_dump_start ()) + mono_handle_native_crash ("SIGABRT", &mctx, info); + else + abort (); } } @@ -246,8 +249,14 @@ MONO_SIG_HANDLER_FUNC (static, sigterm_signal_handler) // Will return when the dumping is done, so this thread can continue // running. Returns FALSE on unrecoverable error. - if (!mono_threads_summarize_execute (&mctx, &output, &hashes, FALSE, NULL, 0)) - g_error ("Crash reporter dumper exited due to fatal error."); + if (mono_dump_start ()) { + // Process was killed from outside since crash reporting wasn't running yet. + mono_handle_native_crash ("SIGTERM", &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)) + g_error ("Crash reporter dumper exited due to fatal error."); + } #endif mono_chain_signal (MONO_SIG_HANDLER_PARAMS); @@ -965,11 +974,13 @@ dump_native_stacktrace (const char *signal, MonoContext *mctx) dump_for_merp = mono_merp_enabled (); #endif +#ifndef DISABLE_STRUCTURED_CRASH + mini_register_sigterm_handler (); +#endif + if (!dump_for_merp) { #ifdef DISABLE_STRUCTURED_CRASH leave = TRUE; -#else - mini_register_sigterm_handler (); #endif } @@ -1051,7 +1062,6 @@ dump_native_stacktrace (const char *signal, MonoContext *mctx) g_async_safe_printf("\nThe MERP upload step has succeeded.\n"); mono_summarize_timeline_phase_log (MonoSummaryDone); } - mono_summarize_toggle_assertions (FALSE); } else { g_async_safe_printf("\nMerp dump step not run, no dump created.\n"); @@ -1116,7 +1126,6 @@ void mono_dump_native_crash_info (const char *signal, MonoContext *mctx, MONO_SIG_HANDLER_INFO_TYPE *info) { dump_native_stacktrace (signal, mctx); - dump_memory_around_ip (mctx); } diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c index 4887061e306..f00d5ba9f95 100644 --- a/mono/mini/mini-runtime.c +++ b/mono/mini/mini-runtime.c @@ -69,6 +69,7 @@ #include #include #include +#include #include #include @@ -3225,7 +3226,8 @@ MONO_SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler) goto exit; mono_sigctx_to_monoctx (ctx, &mctx); - mono_handle_native_crash ("SIGFPE", &mctx, info); + if (mono_dump_start ()) + mono_handle_native_crash ("SIGFPE", &mctx, info); if (mono_do_crash_chaining) { mono_chain_signal (MONO_SIG_HANDLER_PARAMS); goto exit; @@ -3248,7 +3250,8 @@ MONO_SIG_HANDLER_FUNC (, mono_sigill_signal_handler) exit (1); mono_sigctx_to_monoctx (ctx, &mctx); - mono_handle_native_crash ("SIGILL", &mctx, info); + if (mono_dump_start ()) + mono_handle_native_crash ("SIGILL", &mctx, info); if (mono_do_crash_chaining) { mono_chain_signal (MONO_SIG_HANDLER_PARAMS); return; @@ -3329,7 +3332,8 @@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler) if (!mono_domain_get () || !jit_tls) { if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS)) return; - mono_handle_native_crash ("SIGSEGV", &mctx, info); + if (mono_dump_start()) + mono_handle_native_crash ("SIGSEGV", &mctx, info); if (mono_do_crash_chaining) { mono_chain_signal (MONO_SIG_HANDLER_PARAMS); return; @@ -3371,7 +3375,8 @@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler) mono_arch_handle_altstack_exception (ctx, info, info->si_addr, FALSE); } else { // FIXME: This shouldn't run on the altstack - mono_handle_native_crash ("SIGSEGV", &mctx, info); + if (mono_dump_start ()) + mono_handle_native_crash ("SIGSEGV", &mctx, info); } #endif } @@ -3381,7 +3386,8 @@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler) if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS)) return; - mono_handle_native_crash ("SIGSEGV", &mctx, (MONO_SIG_HANDLER_INFO_TYPE*)info); + if (mono_dump_start ()) + mono_handle_native_crash ("SIGSEGV", &mctx, (MONO_SIG_HANDLER_INFO_TYPE*)info); if (mono_do_crash_chaining) { mono_chain_signal (MONO_SIG_HANDLER_PARAMS); @@ -3392,7 +3398,8 @@ MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler) if (mono_is_addr_implicit_null_check (fault_addr)) { mono_arch_handle_exception (ctx, NULL); } else { - mono_handle_native_crash ("SIGSEGV", &mctx, (MONO_SIG_HANDLER_INFO_TYPE*)info); + if (mono_dump_start ()) + mono_handle_native_crash ("SIGSEGV", &mctx, (MONO_SIG_HANDLER_INFO_TYPE*)info); } #endif } diff --git a/mono/utils/mono-state.c b/mono/utils/mono-state.c index 85d49755917..f56239b5e0f 100644 --- a/mono/utils/mono-state.c +++ b/mono/utils/mono-state.c @@ -8,11 +8,13 @@ * (C) 2018 Microsoft, Inc. * */ -#ifndef DISABLE_CRASH_REPORTING - #include #include #include +#include + +#ifndef DISABLE_CRASH_REPORTING + #include #include #include @@ -1152,3 +1154,17 @@ mono_crash_dump (const char *jsonFile, MonoStackHash *hashes) } #endif // DISABLE_CRASH_REPORTING + +static volatile int32_t dump_status; + +gboolean +mono_dump_start (void) +{ + return (mono_atomic_xchg_i32(&dump_status, 1) == 0); // return true if we started the dump +} + +gboolean +mono_dump_complete (void) +{ + return (mono_atomic_xchg_i32(&dump_status, 0) == 1); // return true if we completed the dump +} diff --git a/mono/utils/mono-state.h b/mono/utils/mono-state.h index acc6b2850d9..5a736efaf49 100644 --- a/mono/utils/mono-state.h +++ b/mono/utils/mono-state.h @@ -118,4 +118,12 @@ void mono_state_free_mem (MonoStateMem *mem); #endif // DISABLE_CRASH_REPORTING + +// Dump context functions (enter/leave) + +gboolean +mono_dump_start (void); +gboolean +mono_dump_complete (void); + #endif // MONO_UTILS_NATIVE_STATE diff --git a/msvc/libmonoutils-common.targets b/msvc/libmonoutils-common.targets index 61dbc4f7c8b..210c41e0493 100644 --- a/msvc/libmonoutils-common.targets +++ b/msvc/libmonoutils-common.targets @@ -197,6 +197,8 @@ + + diff --git a/msvc/libmonoutils-common.targets.filters b/msvc/libmonoutils-common.targets.filters index 5ab21b4285b..9c26c4a93e2 100644 --- a/msvc/libmonoutils-common.targets.filters +++ b/msvc/libmonoutils-common.targets.filters @@ -472,6 +472,12 @@ Header Files$(MonoUtilsFilterSubFolder)\common + + Header Files$(MonoUtilsFilterSubFolder)\common + + + Header Files$(MonoUtilsFilterSubFolder)\common + -- 2.11.4.GIT