summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs21
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/UnhandledExceptionArgs.cs20
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj2
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.cpp13
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.h3
5 files changed, 57 insertions, 2 deletions
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 0000000000..702a6c76ba
--- /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
+ {
+ /// <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));
+ }
+ }
+}
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 0000000000..be01674568
--- /dev/null
+++ b/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;
+ }
+ }
+}
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
index 7c1a23d510..a7aa977720 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
+++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj
@@ -37,6 +37,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" />
@@ -56,6 +57,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" />
diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp
index 65e2680905..fa93c6533a 100644
--- a/modules/mono/mono_gd/gd_mono_internals.cpp
+++ b/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
diff --git a/modules/mono/mono_gd/gd_mono_internals.h b/modules/mono/mono_gd/gd_mono_internals.h
index 34d2d35b2d..26eb270eee 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