From 6061ff7ba11d3123bc4a2d7981a31b735f5dcf8d Mon Sep 17 00:00:00 2001 From: Ilya Kuznetsov Date: Thu, 18 Feb 2021 16:18:33 +0100 Subject: [PATCH] Added mono_unhandled_exception call to unhandled_exception hook --- .../Core/GodotUnhandledExceptionEvent.cs | 21 +++++++++++++++++++ .../GodotSharp/Core/UnhandledExceptionArgs.cs | 20 ++++++++++++++++++ .../GodotSharp/GodotSharp/GodotSharp.csproj | 2 ++ modules/mono/mono_gd/gd_mono_internals.cpp | 13 +++++++++++- modules/mono/mono_gd/gd_mono_internals.h | 3 ++- 5 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs create mode 100644 modules/mono/glue/GodotSharp/GodotSharp/Core/UnhandledExceptionArgs.cs diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs new file mode 100644 index 00000000000..702a6c76baa --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Godot +{ + public static partial class GD + { + /// + /// Fires when an unhandled exception occurs, regardless of project settings. + /// + public static event EventHandler UnhandledException; + + private static void OnUnhandledException(Exception e) + { + UnhandledException?.Invoke(null, new UnhandledExceptionArgs(e)); + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/UnhandledExceptionArgs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/UnhandledExceptionArgs.cs new file mode 100644 index 00000000000..be016745689 --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/UnhandledExceptionArgs.cs @@ -0,0 +1,20 @@ +using System; + +namespace Godot +{ + /// + /// Event arguments for when unhandled exceptions occur. + /// + public class UnhandledExceptionArgs + { + /// + /// Exception object + /// + public Exception Exception { get; private set; } + + internal UnhandledExceptionArgs(Exception exception) + { + Exception = exception; + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj index 7c1a23d510d..a7aa977720b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj +++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj @@ -37,6 +37,7 @@ + @@ -56,6 +57,7 @@ + diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp index 65e2680905d..fa93c6533a4 100644 --- a/modules/mono/mono_gd/gd_mono_internals.cpp +++ b/modules/mono/mono_gd/gd_mono_internals.cpp @@ -43,7 +43,6 @@ #include namespace GDMonoInternals { - void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) { // This method should not fail @@ -113,9 +112,11 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) { void unhandled_exception(MonoException *p_exc) { mono_print_unhandled_exception((MonoObject *)p_exc); + gd_unhandled_exception_event(p_exc); if (GDMono::get_singleton()->get_unhandled_exception_policy() == GDMono::POLICY_TERMINATE_APP) { // Too bad 'mono_invoke_unhandled_exception_hook' is not exposed to embedders + mono_unhandled_exception((MonoObject *)p_exc); GDMono::unhandled_exception_hook((MonoObject *)p_exc, nullptr); GD_UNREACHABLE(); } else { @@ -127,4 +128,14 @@ void unhandled_exception(MonoException *p_exc) { #endif } } + +void gd_unhandled_exception_event(MonoException *p_exc) { + MonoImage *mono_image = GDMono::get_singleton()->get_core_api_assembly()->get_image(); + + MonoClass *gd_klass = mono_class_from_name(mono_image, "Godot", "GD"); + MonoMethod *unhandled_exception_method = mono_class_get_method_from_name(gd_klass, "OnUnhandledException", -1); + void *args[1]; + args[0] = p_exc; + mono_runtime_invoke(unhandled_exception_method, nullptr, (void **)args, nullptr); +} } // namespace GDMonoInternals diff --git a/modules/mono/mono_gd/gd_mono_internals.h b/modules/mono/mono_gd/gd_mono_internals.h index 34d2d35b2db..26eb270eee0 100644 --- a/modules/mono/mono_gd/gd_mono_internals.h +++ b/modules/mono/mono_gd/gd_mono_internals.h @@ -38,7 +38,6 @@ #include "core/object/class_db.h" namespace GDMonoInternals { - void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged); /** @@ -46,6 +45,8 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged); * Use GDMonoUtils::debug_unhandled_exception(MonoException *) instead. */ void unhandled_exception(MonoException *p_exc); + +void gd_unhandled_exception_event(MonoException *p_exc); } // namespace GDMonoInternals #endif // GD_MONO_INTERNALS_H