From b57728ebdbbdc67e3920d2c617a29992902f1fe9 Mon Sep 17 00:00:00 2001 From: Bill Holmes Date: Fri, 14 Aug 2026 16:38:01 -0400 Subject: [PATCH] Skip native crash reporting when embedded in Unity mono_handle_native_crash prints a large "Native Crash Reporting" banner, dumps native crash info, and walks the managed stack on every native crash. Unity has its own crash reporting and mono's output is just noise and can cause additional crashes that interrupt the Unity handler. Gate the diagnostic section on the embedding host name: skip it when a non-default host name has been set via mono_unity_set_embeddinghostname, which the standalone mono driver never does. Crash chaining (mono_post_native_crash_handler) still runs unconditionally so the host's handler is invoked. --- mono/metadata/unity-utils.c | 6 +++++ mono/metadata/unity-utils.h | 2 ++ mono/mini/mini-exceptions.c | 44 +++++++++++++++++++++---------------- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/mono/metadata/unity-utils.c b/mono/metadata/unity-utils.c index f35c615d59c7..7f6e1eb3d1a0 100644 --- a/mono/metadata/unity-utils.c +++ b/mono/metadata/unity-utils.c @@ -69,6 +69,12 @@ MonoString* mono_unity_get_embeddinghostname() return mono_string_new_wrapper(gEmbeddingHostName->str); } + +gboolean mono_unity_embedding_host_name_is_set (void) +{ + return gEmbeddingHostName != NULL && strcmp (gEmbeddingHostName->str, "mono") != 0; +} + static gboolean socket_security_enabled = FALSE; gboolean diff --git a/mono/metadata/unity-utils.h b/mono/metadata/unity-utils.h index 121232333b80..1dcc6af0d0a9 100644 --- a/mono/metadata/unity-utils.h +++ b/mono/metadata/unity-utils.h @@ -55,6 +55,8 @@ void unity_mono_close_output(void); extern MonoString* mono_unity_get_embeddinghostname(void); +extern gboolean mono_unity_embedding_host_name_is_set (void); + #ifdef WIN32 FILE* unity_fopen( const char *name, const char *mode ); #endif diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c index b804fa915610..a3b620c58f80 100644 --- a/mono/mini/mini-exceptions.c +++ b/mono/mini/mini-exceptions.c @@ -62,6 +62,7 @@ #include #include #include +#include #include #include #include @@ -3483,25 +3484,30 @@ mono_handle_native_crash (const char *signal, MonoContext *mctx, MONO_SIG_HANDLE * with ones which have a greater chance of working. */ - g_async_safe_printf("\n=================================================================\n"); - g_async_safe_printf("\tNative Crash Reporting\n"); - g_async_safe_printf("=================================================================\n"); - g_async_safe_printf("Got a %s while executing native code. This usually indicates\n", signal); - g_async_safe_printf("a fatal error in the mono runtime or one of the native libraries \n"); - g_async_safe_printf("used by your application.\n"); - g_async_safe_printf("=================================================================\n"); - mono_dump_native_crash_info (signal, mctx, info); - - /* !jit_tls means the thread was not registered with the runtime */ - // This must be below the native crash dump, because we can't safely - // do runtime state probing after we have walked the managed stack here. - if (jit_tls && mono_thread_internal_current () && mctx) { - g_async_safe_printf ("\n=================================================================\n"); - g_async_safe_printf ("\tManaged Stacktrace:\n"); - g_async_safe_printf ("=================================================================\n"); - - mono_walk_stack_full (print_stack_frame_signal_safe, mctx, mono_domain_get (), jit_tls, mono_get_lmf (), MONO_UNWIND_LOOKUP_IL_OFFSET, NULL, TRUE); - g_async_safe_printf ("=================================================================\n"); + /* When embedded in a host application (e.g. Unity), skip Mono's own crash + * diagnostics; the host has its own crash reporting. We still chain to the + * host handler below. */ + if (!mono_unity_embedding_host_name_is_set ()) { + g_async_safe_printf("\n=================================================================\n"); + g_async_safe_printf("\tNative Crash Reporting\n"); + g_async_safe_printf("=================================================================\n"); + g_async_safe_printf("Got a %s while executing native code. This usually indicates\n", signal); + g_async_safe_printf("a fatal error in the mono runtime or one of the native libraries \n"); + g_async_safe_printf("used by your application.\n"); + g_async_safe_printf("=================================================================\n"); + mono_dump_native_crash_info (signal, mctx, info); + + /* !jit_tls means the thread was not registered with the runtime */ + // This must be below the native crash dump, because we can't safely + // do runtime state probing after we have walked the managed stack here. + if (jit_tls && mono_thread_internal_current () && mctx) { + g_async_safe_printf ("\n=================================================================\n"); + g_async_safe_printf ("\tManaged Stacktrace:\n"); + g_async_safe_printf ("=================================================================\n"); + + mono_walk_stack_full (print_stack_frame_signal_safe, mctx, mono_domain_get (), jit_tls, mono_get_lmf (), MONO_UNWIND_LOOKUP_IL_OFFSET, NULL, TRUE); + g_async_safe_printf ("=================================================================\n"); + } } mono_post_native_crash_handler (signal, mctx, info, mono_do_crash_chaining);