[merp] Introduce a new 'dump mode' that allows different signal behavior when dumping...
authorAlexis Christoforides <alexis@thenull.net>
Sat, 26 Oct 2019 22:48:40 +0000 (18:48 -0400)
committerAleksey Kliger (λgeek) <alklig@microsoft.com>
Sat, 26 Oct 2019 22:48:40 +0000 (18:48 -0400)
* 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.

Commit migrated from https://github.com/mono/mono/commit/db568c6fe0cb5eab71ed729ec5b412365eacf280

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/utils/mono-state.c
src/mono/mono/utils/mono-state.h
src/mono/msvc/libmonoutils-common.targets
src/mono/msvc/libmonoutils-common.targets.filters

index daca2a9..4ea18a5 100644 (file)
@@ -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;
index 88224bd..636707e 100644 (file)
@@ -36,6 +36,7 @@
 #include <mono/metadata/gc-internals.h>
 #include <mono/metadata/mono-debug.h>
 #include <mono/utils/mono-mmap.h>
+#include <mono/utils/mono-state.h>
 
 #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;
 
index fc55044..c251ccd 100644 (file)
@@ -27,6 +27,7 @@
 #include <mono/metadata/debug-helpers.h>
 #include <mono/metadata/exception.h>
 #include <mono/metadata/mono-debug.h>
+#include <mono/utils/mono-state.h>
 
 #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:
index a55402b..68e406f 100644 (file)
@@ -27,6 +27,7 @@
 #include <mono/metadata/gc-internals.h>
 #include <mono/metadata/mono-debug.h>
 #include <mono/utils/mono-mmap.h>
+#include <mono/utils/mono-state.h>
 
 #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.
index 0f86b29..7122baa 100644 (file)
@@ -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);
 }
 
index 4887061..f00d5ba 100644 (file)
@@ -69,6 +69,7 @@
 #include <mono/utils/checked-build.h>
 #include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-proclib.h>
+#include <mono/utils/mono-state.h>
 #include <mono/metadata/w32handle.h>
 #include <mono/metadata/threadpool.h>
 
@@ -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
 }
index 85d4975..f56239b 100644 (file)
@@ -8,11 +8,13 @@
  * (C) 2018 Microsoft, Inc.
  *
  */
-#ifndef DISABLE_CRASH_REPORTING
-
 #include <config.h>
 #include <glib.h>
 #include <mono/utils/mono-state.h>
+#include <mono/utils/atomic.h>
+
+#ifndef DISABLE_CRASH_REPORTING
+
 #include <mono/utils/mono-threads-coop.h>
 #include <mono/metadata/object-internals.h>
 #include <mono/metadata/mono-config-dirs.h>
@@ -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
+}
index acc6b28..5a736ef 100644 (file)
@@ -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
index 61dbc4f..210c41e 100644 (file)
     <ClInclude Include="$(MonoSourceLocation)\mono\utils\refcount.h" />
     <ClInclude Include="$(MonoSourceLocation)\mono\utils\w32api.h" />
     <ClInclude Include="$(MonoSourceLocation)\mono\utils\unlocked.h" />
+    <ClCompile Include="$(MonoSourceLocation)\mono\utils\mono-state.c" />
+    <ClInclude Include="$(MonoSourceLocation)\mono\utils\mono-state.h" />
   </ItemGroup>
   <ItemGroup Label="libmonoutilsinclude_headers">
     <ClInclude Include="$(MonoSourceLocation)\mono\utils\mono-logger.h" />
index 5ab21b4..9c26c4a 100644 (file)
     <ClInclude Include="$(MonoSourceLocation)\mono\utils\unlocked.h">
       <Filter>Header Files$(MonoUtilsFilterSubFolder)\common</Filter>
     </ClInclude>
+    <ClCompile Include="$(MonoSourceLocation)\mono\utils\mono-state.c">
+      <Filter>Header Files$(MonoUtilsFilterSubFolder)\common</Filter>
+    </ClCompile>
+    <ClInclude Include="$(MonoSourceLocation)\mono\utils\mono-state.h">
+      <Filter>Header Files$(MonoUtilsFilterSubFolder)\common</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup Label="libmonoutilsinclude_headers">
     <ClInclude Include="$(MonoSourceLocation)\mono\utils\mono-logger.h">