Browse Source

Merge pull request #46174 from xill47/mono-appdomain-unhandled-exception-event

Added mono_unhandled_exception call to unhandled_exception hook
Rémi Verschelde 4 years ago
parent
commit
26d1b30d35

+ 21 - 0
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
+    {
+        /// <summary>
+        /// Fires when an unhandled exception occurs, regardless of project settings.
+        /// </summary>
+        public static event EventHandler<UnhandledExceptionArgs> UnhandledException;
+
+        private static void OnUnhandledException(Exception e)
+        {
+            UnhandledException?.Invoke(null, new UnhandledExceptionArgs(e));
+        }
+    }
+}

+ 20 - 0
modules/mono/glue/GodotSharp/GodotSharp/Core/UnhandledExceptionArgs.cs

@@ -0,0 +1,20 @@
+using System;
+
+namespace Godot
+{
+    /// <summary>
+    /// Event arguments for when unhandled exceptions occur.
+    /// </summary>
+    public class UnhandledExceptionArgs
+    {
+        /// <summary>
+        /// Exception object
+        /// </summary>
+        public Exception Exception { get; private set; }
+
+        internal UnhandledExceptionArgs(Exception exception)
+        {
+            Exception = exception;
+        }
+    }
+}

+ 2 - 0
modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj

@@ -40,6 +40,7 @@
     <Compile Include="Core\GodotSynchronizationContext.cs" />
     <Compile Include="Core\GodotTaskScheduler.cs" />
     <Compile Include="Core\GodotTraceListener.cs" />
+    <Compile Include="Core\GodotUnhandledExceptionEvent.cs" />
     <Compile Include="Core\Interfaces\IAwaitable.cs" />
     <Compile Include="Core\Interfaces\IAwaiter.cs" />
     <Compile Include="Core\Interfaces\ISerializationListener.cs" />
@@ -59,6 +60,7 @@
     <Compile Include="Core\StringName.cs" />
     <Compile Include="Core\Transform.cs" />
     <Compile Include="Core\Transform2D.cs" />
+    <Compile Include="Core\UnhandledExceptionArgs.cs" />
     <Compile Include="Core\Vector2.cs" />
     <Compile Include="Core\Vector2i.cs" />
     <Compile Include="Core\Vector3.cs" />

+ 12 - 1
modules/mono/mono_gd/gd_mono_internals.cpp

@@ -43,7 +43,6 @@
 #include <mono/metadata/exception.h>
 
 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

+ 2 - 1
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