From 6d6e2064757c0b3fb4ed4ea7a9a82f6beee2186f Mon Sep 17 00:00:00 2001 From: Alexis Christoforides Date: Thu, 27 Feb 2020 17:52:06 -0500 Subject: [PATCH] [merp] Create a 'reason' breadcrumb for the crash dump process For example, the system name of a signal ('segv') or 'MANAGED_EXCEPTION' are typical arguments. --- mono/metadata/icall.c | 4 ++-- mono/mini/mini-posix.c | 2 +- mono/utils/mono-state.c | 42 +++++++++++++++++++++++++++++++++-------- mono/utils/mono-state.h | 2 +- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index 7d4c7a22d202..b7e13713cd41 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -6480,7 +6480,7 @@ ves_icall_Mono_Runtime_ExceptionToState (MonoExceptionHandle exc_handle, guint64 // FIXME: Push handles down into mini/mini-exceptions.c MonoException *exc = MONO_HANDLE_RAW (exc_handle); MonoThreadSummary out; - mono_summarize_timeline_start (); + mono_summarize_timeline_start ("ExceptionToState"); mono_summarize_timeline_phase_log (MonoSummarySuspendHandshake); mono_summarize_timeline_phase_log (MonoSummaryUnmanagedStacks); mono_get_eh_callbacks ()->mono_summarize_exception (exc, &out); @@ -6643,7 +6643,7 @@ ves_icall_Mono_Runtime_DumpStateTotal (guint64 *portable_hash, guint64 *unportab mono_get_runtime_callbacks ()->install_state_summarizer (); - mono_summarize_timeline_start (); + mono_summarize_timeline_start ("DumpStateTotal"); gboolean success = mono_threads_summarize (ctx, &out, &hashes, TRUE, FALSE, scratch, MONO_MAX_SUMMARY_LEN_ICALL); mono_summarize_timeline_phase_log (MonoSummaryCleanup); diff --git a/mono/mini/mini-posix.c b/mono/mini/mini-posix.c index 05290c1dd65f..7f9537423d17 100644 --- a/mono/mini/mini-posix.c +++ b/mono/mini/mini-posix.c @@ -1027,7 +1027,7 @@ dump_native_stacktrace (const char *signal, MonoContext *mctx) g_async_safe_printf ("=================================================================\n"); if (!leave) { - mono_summarize_timeline_start (); + mono_summarize_timeline_start (signal); mono_summarize_toggle_assertions (TRUE); int mono_max_summary_len = 10000000; diff --git a/mono/utils/mono-state.c b/mono/utils/mono-state.c index 1c8c65b8b869..6b53a37bb60d 100644 --- a/mono/utils/mono-state.c +++ b/mono/utils/mono-state.c @@ -145,18 +145,43 @@ static const char *configured_timeline_dir; static MonoSummaryTimeline log; static void -file_for_summary_stage (const char *directory, MonoSummaryStage stage, gchar *buff, size_t sizeof_buff) +file_for_stage_breadcrumb (const char *directory, MonoSummaryStage stage, gchar *buff, size_t sizeof_buff) { g_snprintf (buff, sizeof_buff, "%s%scrash_stage_%d", directory, G_DIR_SEPARATOR_S, stage); } static void -create_stage_mark_file (void) +file_for_dump_reason_breadcrumb (const char *directory, const char *dump_reason, gchar *buff, size_t sizeof_buff) +{ + g_snprintf (buff, sizeof_buff, "%s%scrash_reason_%s", directory, G_DIR_SEPARATOR_S, dump_reason); +} + +static void create_breadcrumb (const char *path) +{ + int handle = g_open (path, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); + if (handle < 0) { + g_async_safe_printf ("Failed to create breadcrumb file %s\n", path); + return; + } + + if (close(handle) < 0) + g_async_safe_printf ("Failed to close breadcrumb file %s\n", path); +} + +static void +create_stage_breadcrumb (void) +{ + char out_file [200]; + file_for_stage_breadcrumb (log.directory, log.level, out_file, sizeof(out_file)); + create_breadcrumb (out_file); +} + +static void +create_dump_reason_breadcrumb (const char *dump_reason) { char out_file [200]; - file_for_summary_stage (log.directory, log.level, out_file, sizeof(out_file)); - int handle = g_open (out_file, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); - close(handle); + file_for_dump_reason_breadcrumb (log.directory, dump_reason, out_file, sizeof(out_file)); + create_breadcrumb (out_file); } gboolean @@ -172,7 +197,7 @@ mono_summarize_set_timeline_dir (const char *directory) } void -mono_summarize_timeline_start (void) +mono_summarize_timeline_start (const char *dump_reason) { memset (&log, 0, sizeof (log)); @@ -180,6 +205,7 @@ mono_summarize_timeline_start (void) return; log.directory = configured_timeline_dir; + create_dump_reason_breadcrumb (dump_reason); mono_summarize_timeline_phase_log (MonoSummarySetup); } @@ -246,7 +272,7 @@ mono_summarize_timeline_phase_log (MonoSummaryStage next) g_assertf(out_level == next || next == MonoSummaryDoubleFault, "Log Error: Log transition to %d, actual expected next step is %d\n", next, out_level); log.level = out_level; - create_stage_mark_file (); + create_stage_breadcrumb (); // To check, comment out normally // DO NOT MERGE UNCOMMENTED // As this does a lot of FILE io @@ -323,7 +349,7 @@ static gboolean timeline_has_level (const char *directory, char *log_file, size_t log_file_size, gboolean clear, MonoSummaryStage stage) { memset (log_file, 0, log_file_size); - file_for_summary_stage (directory, stage, log_file, log_file_size); + file_for_stage_breadcrumb (directory, stage, log_file, log_file_size); gboolean exists = g_file_test (log_file, G_FILE_TEST_EXISTS); if (clear && exists) remove (log_file); diff --git a/mono/utils/mono-state.h b/mono/utils/mono-state.h index 994755a8e9b4..8b5e6b4dec05 100644 --- a/mono/utils/mono-state.h +++ b/mono/utils/mono-state.h @@ -57,7 +57,7 @@ gboolean mono_summarize_set_timeline_dir (const char *directory); void -mono_summarize_timeline_start (void); +mono_summarize_timeline_start (const char *dump_reason); void mono_summarize_timeline_phase_log (MonoSummaryStage stage);