Added mono_unhandled_exception call to unhandled_exception hook

(cherry picked from commit 6061ff7ba1)
This commit is contained in:
Ilya Kuznetsov 2021-02-18 16:18:33 +01:00 committed by Rémi Verschelde
parent 33628c482f
commit cacf96962d
No known key found for this signature in database
GPG key ID: C3336907360768E1
5 changed files with 55 additions and 2 deletions

View file

@ -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));
}
}
}

View file

@ -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;
}
}
}

View file

@ -34,6 +34,7 @@
<Compile Include="Core\GodotSynchronizationContext.cs" /> <Compile Include="Core\GodotSynchronizationContext.cs" />
<Compile Include="Core\GodotTaskScheduler.cs" /> <Compile Include="Core\GodotTaskScheduler.cs" />
<Compile Include="Core\GodotTraceListener.cs" /> <Compile Include="Core\GodotTraceListener.cs" />
<Compile Include="Core\GodotUnhandledExceptionEvent.cs" />
<Compile Include="Core\Interfaces\IAwaitable.cs" /> <Compile Include="Core\Interfaces\IAwaitable.cs" />
<Compile Include="Core\Interfaces\IAwaiter.cs" /> <Compile Include="Core\Interfaces\IAwaiter.cs" />
<Compile Include="Core\Interfaces\ISerializationListener.cs" /> <Compile Include="Core\Interfaces\ISerializationListener.cs" />
@ -50,6 +51,7 @@
<Compile Include="Core\StringExtensions.cs" /> <Compile Include="Core\StringExtensions.cs" />
<Compile Include="Core\Transform.cs" /> <Compile Include="Core\Transform.cs" />
<Compile Include="Core\Transform2D.cs" /> <Compile Include="Core\Transform2D.cs" />
<Compile Include="Core\UnhandledExceptionArgs.cs" />
<Compile Include="Core\Vector2.cs" /> <Compile Include="Core\Vector2.cs" />
<Compile Include="Core\Vector3.cs" /> <Compile Include="Core\Vector3.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />

View file

@ -41,7 +41,6 @@
#include <mono/metadata/exception.h> #include <mono/metadata/exception.h>
namespace GDMonoInternals { namespace GDMonoInternals {
void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) { void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
// This method should not fail // This method should not fail
@ -112,9 +111,11 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
void unhandled_exception(MonoException *p_exc) { void unhandled_exception(MonoException *p_exc) {
mono_print_unhandled_exception((MonoObject *)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) { if (GDMono::get_singleton()->get_unhandled_exception_policy() == GDMono::POLICY_TERMINATE_APP) {
// Too bad 'mono_invoke_unhandled_exception_hook' is not exposed to embedders // 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, NULL); GDMono::unhandled_exception_hook((MonoObject *)p_exc, NULL);
GD_UNREACHABLE(); GD_UNREACHABLE();
} else { } else {
@ -126,4 +127,13 @@ void unhandled_exception(MonoException *p_exc) {
} }
} }
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 } // namespace GDMonoInternals

View file

@ -38,7 +38,6 @@
#include "core/object.h" #include "core/object.h"
namespace GDMonoInternals { namespace GDMonoInternals {
void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged); void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged);
/** /**
@ -47,6 +46,7 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged);
*/ */
void unhandled_exception(MonoException *p_exc); void unhandled_exception(MonoException *p_exc);
void gd_unhandled_exception_event(MonoException *p_exc);
} // namespace GDMonoInternals } // namespace GDMonoInternals
#endif // GD_MONO_INTERNALS_H #endif // GD_MONO_INTERNALS_H