瀏覽代碼

C#: Re-introduce exception logging and error stack traces in editor

These two had been disabled while moving to .NET 5, as the previous
implementation relied on Mono embedding APIs.
Ignacio Roldán Etcheverry 3 年之前
父節點
當前提交
778007a358

+ 5 - 77
modules/mono/csharp_script.cpp

@@ -104,7 +104,7 @@ Error CSharpLanguage::execute_file(const String &p_path) {
 	return OK;
 	return OK;
 }
 }
 
 
-extern void *godotsharp_pinvoke_funcs[181];
+extern void *godotsharp_pinvoke_funcs[185];
 [[maybe_unused]] volatile void **do_not_strip_godotsharp_pinvoke_funcs;
 [[maybe_unused]] volatile void **do_not_strip_godotsharp_pinvoke_funcs;
 #ifdef TOOLS_ENABLED
 #ifdef TOOLS_ENABLED
 extern void *godotsharp_editor_pinvoke_funcs[30];
 extern void *godotsharp_editor_pinvoke_funcs[30];
@@ -592,8 +592,6 @@ String CSharpLanguage::debug_get_stack_level_source(int p_level) const {
 	return String();
 	return String();
 }
 }
 
 
-#warning TODO
-#if 0
 Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info() {
 Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info() {
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	// Printing an error here will result in endless recursion, so we must be careful
 	// Printing an error here will result in endless recursion, so we must be careful
@@ -606,91 +604,21 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info()
 		_recursion_flag_ = false;
 		_recursion_flag_ = false;
 	};
 	};
 
 
-	GD_MONO_SCOPE_THREAD_ATTACH;
-
-	if (!gdmono->is_runtime_initialized() || !GDMono::get_singleton()->get_core_api_assembly() || !GDMonoCache::cached_data.corlib_cache_updated) {
-		return Vector<StackInfo>();
-	}
-
-	MonoObject *stack_trace = mono_object_new(mono_domain_get(), CACHED_CLASS(System_Diagnostics_StackTrace)->get_mono_ptr());
-
-	MonoBoolean need_file_info = true;
-	void *ctor_args[1] = { &need_file_info };
-
-	CACHED_METHOD(System_Diagnostics_StackTrace, ctor_bool)->invoke_raw(stack_trace, ctor_args);
-
-	Vector<StackInfo> si;
-	si = stack_trace_get_info(stack_trace);
-
-	return si;
-#else
-	return Vector<StackInfo>();
-#endif
-}
-
-#ifdef DEBUG_ENABLED
-Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObject *p_stack_trace) {
-	// Printing an error here will result in endless recursion, so we must be careful
-	static thread_local bool _recursion_flag_ = false;
-	if (_recursion_flag_) {
-		return Vector<StackInfo>();
-	}
-	_recursion_flag_ = true;
-	SCOPE_EXIT {
-		_recursion_flag_ = false;
-	};
-
-	GD_MONO_SCOPE_THREAD_ATTACH;
-
-	MonoException *exc = nullptr;
-
-	MonoArray *frames = CACHED_METHOD_THUNK(System_Diagnostics_StackTrace, GetFrames).invoke(p_stack_trace, &exc);
-
-	if (exc) {
-		GDMonoUtils::debug_print_unhandled_exception(exc);
-		return Vector<StackInfo>();
-	}
-
-	int frame_count = mono_array_length(frames);
-
-	if (frame_count <= 0) {
+	if (!gdmono->is_runtime_initialized()) {
 		return Vector<StackInfo>();
 		return Vector<StackInfo>();
 	}
 	}
 
 
 	Vector<StackInfo> si;
 	Vector<StackInfo> si;
-	si.resize(frame_count);
-
-	for (int i = 0; i < frame_count; i++) {
-		StackInfo &sif = si.write[i];
-		MonoObject *frame = mono_array_get(frames, MonoObject *, i);
 
 
-		MonoString *file_name;
-		int file_line_num;
-		MonoString *method_decl;
-		CACHED_METHOD_THUNK(DebuggingUtils, GetStackFrameInfo).invoke(frame, &file_name, &file_line_num, &method_decl, &exc);
-
-		if (exc) {
-			GDMonoUtils::debug_print_unhandled_exception(exc);
-			return Vector<StackInfo>();
-		}
-
-		// TODO
-		// what if the StackFrame method is null (method_decl is empty). should we skip this frame?
-		// can reproduce with a MissingMethodException on internal calls
-
-		sif.file = GDMonoMarshal::mono_string_to_godot(file_name);
-		sif.line = file_line_num;
-		sif.func = GDMonoMarshal::mono_string_to_godot(method_decl);
+	if (GDMonoCache::godot_api_cache_updated) {
+		GDMonoCache::managed_callbacks.DebuggingUtils_GetCurrentStackInfo(&si);
 	}
 	}
 
 
 	return si;
 	return si;
-}
-#endif
 #else
 #else
-Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info() {
 	return Vector<StackInfo>();
 	return Vector<StackInfo>();
-}
 #endif
 #endif
+}
 
 
 void CSharpLanguage::post_unsafe_reference(Object *p_obj) {
 void CSharpLanguage::post_unsafe_reference(Object *p_obj) {
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED

+ 0 - 7
modules/mono/csharp_script.h

@@ -464,13 +464,6 @@ public:
 	static void tie_user_managed_to_unmanaged(GCHandleIntPtr p_gchandle_intptr, Object *p_unmanaged, Ref<CSharpScript> *p_script, bool p_ref_counted);
 	static void tie_user_managed_to_unmanaged(GCHandleIntPtr p_gchandle_intptr, Object *p_unmanaged, Ref<CSharpScript> *p_script, bool p_ref_counted);
 	static void tie_managed_to_unmanaged_with_pre_setup(GCHandleIntPtr p_gchandle_intptr, Object *p_unmanaged);
 	static void tie_managed_to_unmanaged_with_pre_setup(GCHandleIntPtr p_gchandle_intptr, Object *p_unmanaged);
 
 
-#warning TODO
-#if 0
-#ifdef DEBUG_ENABLED
-	Vector<StackInfo> stack_trace_get_info(MonoObject *p_stack_trace);
-#endif
-#endif
-
 	void post_unsafe_reference(Object *p_obj);
 	void post_unsafe_reference(Object *p_obj);
 	void pre_unsafe_unreference(Object *p_obj);
 	void pre_unsafe_unreference(Object *p_obj);
 
 

+ 6 - 6
modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/CSharpInstanceBridge.cs

@@ -39,7 +39,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugPrintUnhandledException(e);
+                ExceptionUtils.LogException(e);
                 *ret = default;
                 *ret = default;
                 return false.ToGodotBool();
                 return false.ToGodotBool();
             }
             }
@@ -69,7 +69,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugPrintUnhandledException(e);
+                ExceptionUtils.LogException(e);
                 return false.ToGodotBool();
                 return false.ToGodotBool();
             }
             }
         }
         }
@@ -107,7 +107,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugPrintUnhandledException(e);
+                ExceptionUtils.LogException(e);
                 *outRet = default;
                 *outRet = default;
                 return false.ToGodotBool();
                 return false.ToGodotBool();
             }
             }
@@ -127,7 +127,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugPrintUnhandledException(e);
+                ExceptionUtils.LogException(e);
             }
             }
         }
         }
 
 
@@ -159,7 +159,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugPrintUnhandledException(e);
+                ExceptionUtils.LogException(e);
                 *outRes = default;
                 *outRes = default;
                 *outValid = false.ToGodotBool();
                 *outValid = false.ToGodotBool();
             }
             }
@@ -179,7 +179,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugPrintUnhandledException(e);
+                ExceptionUtils.LogException(e);
                 return false.ToGodotBool();
                 return false.ToGodotBool();
             }
             }
         }
         }

+ 1 - 1
modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/GCHandleBridge.cs

@@ -15,7 +15,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugPrintUnhandledException(e);
+                ExceptionUtils.LogException(e);
             }
             }
         }
         }
     }
     }

+ 4 - 4
modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ManagedCallbacks.cs

@@ -34,9 +34,9 @@ namespace Godot.Bridge
         public delegate* unmanaged<IntPtr, godot_string*, godot_bool*, void> CSharpInstanceBridge_CallToString;
         public delegate* unmanaged<IntPtr, godot_string*, godot_bool*, void> CSharpInstanceBridge_CallToString;
         public delegate* unmanaged<IntPtr, godot_string_name*, godot_bool> CSharpInstanceBridge_HasMethodUnknownParams;
         public delegate* unmanaged<IntPtr, godot_string_name*, godot_bool> CSharpInstanceBridge_HasMethodUnknownParams;
         public delegate* unmanaged<IntPtr, void> GCHandleBridge_FreeGCHandle;
         public delegate* unmanaged<IntPtr, void> GCHandleBridge_FreeGCHandle;
-        public delegate* unmanaged<void> DebuggingUtils_InstallTraceListener;
-        public delegate* unmanaged<void> Dispatcher_InitializeDefaultGodotTaskScheduler;
+        public delegate* unmanaged<void*, void> DebuggingUtils_GetCurrentStackInfo;
         public delegate* unmanaged<void> DisposablesTracker_OnGodotShuttingDown;
         public delegate* unmanaged<void> DisposablesTracker_OnGodotShuttingDown;
+        public delegate* unmanaged<godot_bool, void> GD_OnCoreApiAssemblyLoaded;
         // @formatter:on
         // @formatter:on
 
 
         public static ManagedCallbacks Create()
         public static ManagedCallbacks Create()
@@ -70,9 +70,9 @@ namespace Godot.Bridge
                 CSharpInstanceBridge_CallToString = &CSharpInstanceBridge.CallToString,
                 CSharpInstanceBridge_CallToString = &CSharpInstanceBridge.CallToString,
                 CSharpInstanceBridge_HasMethodUnknownParams = &CSharpInstanceBridge.HasMethodUnknownParams,
                 CSharpInstanceBridge_HasMethodUnknownParams = &CSharpInstanceBridge.HasMethodUnknownParams,
                 GCHandleBridge_FreeGCHandle = &GCHandleBridge.FreeGCHandle,
                 GCHandleBridge_FreeGCHandle = &GCHandleBridge.FreeGCHandle,
-                DebuggingUtils_InstallTraceListener = &DebuggingUtils.InstallTraceListener,
-                Dispatcher_InitializeDefaultGodotTaskScheduler = &Dispatcher.InitializeDefaultGodotTaskScheduler,
+                DebuggingUtils_GetCurrentStackInfo = &DebuggingUtils.GetCurrentStackInfo,
                 DisposablesTracker_OnGodotShuttingDown = &DisposablesTracker.OnGodotShuttingDown,
                 DisposablesTracker_OnGodotShuttingDown = &DisposablesTracker.OnGodotShuttingDown,
+                GD_OnCoreApiAssemblyLoaded = &GD.OnCoreApiAssemblyLoaded,
                 // @formatter:on
                 // @formatter:on
             };
             };
         }
         }

+ 17 - 17
modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs

@@ -27,7 +27,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugUnhandledException(e);
+                ExceptionUtils.LogException(e);
             }
             }
         }
         }
 
 
@@ -54,7 +54,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugPrintUnhandledException(e);
+                ExceptionUtils.LogException(e);
                 return IntPtr.Zero;
                 return IntPtr.Zero;
             }
             }
         }
         }
@@ -111,7 +111,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugPrintUnhandledException(e);
+                ExceptionUtils.LogException(e);
                 return false.ToGodotBool();
                 return false.ToGodotBool();
             }
             }
         }
         }
@@ -151,7 +151,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugUnhandledException(e);
+                ExceptionUtils.LogException(e);
                 *outRes = default;
                 *outRes = default;
             }
             }
         }
         }
@@ -167,7 +167,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugUnhandledException(e);
+                ExceptionUtils.LogException(e);
             }
             }
         }
         }
 
 
@@ -280,7 +280,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugPrintUnhandledException(e);
+                ExceptionUtils.LogException(e);
                 *outOwnerIsNull = false.ToGodotBool();
                 *outOwnerIsNull = false.ToGodotBool();
             }
             }
         }
         }
@@ -374,7 +374,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugUnhandledException(e);
+                ExceptionUtils.LogException(e);
                 *outRetSignals = NativeFuncs.godotsharp_dictionary_new();
                 *outRetSignals = NativeFuncs.godotsharp_dictionary_new();
             }
             }
         }
         }
@@ -425,7 +425,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugUnhandledException(e);
+                ExceptionUtils.LogException(e);
                 return false.ToGodotBool();
                 return false.ToGodotBool();
             }
             }
         }
         }
@@ -445,7 +445,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugUnhandledException(e);
+                ExceptionUtils.LogException(e);
                 return false.ToGodotBool();
                 return false.ToGodotBool();
             }
             }
         }
         }
@@ -473,7 +473,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugUnhandledException(e);
+                ExceptionUtils.LogException(e);
                 return false.ToGodotBool();
                 return false.ToGodotBool();
             }
             }
         }
         }
@@ -524,7 +524,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugUnhandledException(e);
+                ExceptionUtils.LogException(e);
             }
             }
         }
         }
 
 
@@ -596,7 +596,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugUnhandledException(e);
+                ExceptionUtils.LogException(e);
                 *outTool = false.ToGodotBool();
                 *outTool = false.ToGodotBool();
                 *outRpcFunctionsDest = NativeFuncs.godotsharp_dictionary_new();
                 *outRpcFunctionsDest = NativeFuncs.godotsharp_dictionary_new();
             }
             }
@@ -629,7 +629,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugUnhandledException(e);
+                ExceptionUtils.LogException(e);
                 *outNewGCHandlePtr = IntPtr.Zero;
                 *outNewGCHandlePtr = IntPtr.Zero;
                 return false.ToGodotBool();
                 return false.ToGodotBool();
             }
             }
@@ -665,7 +665,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugUnhandledException(e);
+                ExceptionUtils.LogException(e);
             }
             }
         }
         }
 
 
@@ -757,7 +757,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugUnhandledException(e);
+                ExceptionUtils.LogException(e);
             }
             }
         }
         }
 
 
@@ -794,7 +794,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugUnhandledException(e);
+                ExceptionUtils.LogException(e);
             }
             }
         }
         }
 
 
@@ -882,7 +882,7 @@ namespace Godot.Bridge
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugUnhandledException(e);
+                ExceptionUtils.LogException(e);
             }
             }
         }
         }
     }
     }

+ 81 - 12
modules/mono/glue/GodotSharp/GodotSharp/Core/DebuggingUtils.cs

@@ -1,15 +1,18 @@
 using System;
 using System;
 using System.Diagnostics;
 using System.Diagnostics;
 using System.Reflection;
 using System.Reflection;
+using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
 using System.Text;
 using System.Text;
 using Godot.NativeInterop;
 using Godot.NativeInterop;
 
 
+#nullable enable
+
 namespace Godot
 namespace Godot
 {
 {
     internal static class DebuggingUtils
     internal static class DebuggingUtils
     {
     {
-        internal static void AppendTypeName(this StringBuilder sb, Type type)
+        private static void AppendTypeName(this StringBuilder sb, Type type)
         {
         {
             if (type.IsPrimitive)
             if (type.IsPrimitive)
                 sb.Append(type.Name);
                 sb.Append(type.Name);
@@ -21,28 +24,94 @@ namespace Godot
             sb.Append(' ');
             sb.Append(' ');
         }
         }
 
 
-        [UnmanagedCallersOnly]
         internal static void InstallTraceListener()
         internal static void InstallTraceListener()
+        {
+            Trace.Listeners.Clear();
+            Trace.Listeners.Add(new GodotTraceListener());
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        // ReSharper disable once InconsistentNaming
+        internal ref struct godot_stack_info
+        {
+            public godot_string File;
+            public godot_string Func;
+            public int Line;
+        }
+
+        [StructLayout(LayoutKind.Sequential)]
+        // ReSharper disable once InconsistentNaming
+        internal ref struct godot_stack_info_vector
+        {
+            private IntPtr _writeProxy;
+            private unsafe godot_stack_info* _ptr;
+
+            public readonly unsafe godot_stack_info* Elements
+            {
+                [MethodImpl(MethodImplOptions.AggressiveInlining)]
+                get => _ptr;
+            }
+
+            public void Resize(int size)
+            {
+                if (size < 0)
+                    throw new ArgumentOutOfRangeException(nameof(size));
+                var err = NativeFuncs.godotsharp_stack_info_vector_resize(ref this, size);
+                if (err != Error.Ok)
+                    throw new InvalidOperationException("Failed to resize vector. Error code is: " + err.ToString());
+            }
+
+            public unsafe void Dispose()
+            {
+                if (_ptr == null)
+                    return;
+                NativeFuncs.godotsharp_stack_info_vector_destroy(ref this);
+                _ptr = null;
+            }
+        }
+
+        [UnmanagedCallersOnly]
+        internal static unsafe void GetCurrentStackInfo(void* destVector)
         {
         {
             try
             try
             {
             {
-                Trace.Listeners.Clear();
-                Trace.Listeners.Add(new GodotTraceListener());
+                var vector = (godot_stack_info_vector*)destVector;
+                var stackTrace = new StackTrace(skipFrames: 1, fNeedFileInfo: true);
+                int frameCount = stackTrace.FrameCount;
+
+                if (frameCount == 0)
+                    return;
+
+                vector->Resize(frameCount);
+
+                int i = 0;
+                foreach (StackFrame frame in stackTrace.GetFrames())
+                {
+                    string? fileName = frame.GetFileName();
+                    int fileLineNumber = frame.GetFileLineNumber();
+
+                    GetStackFrameMethodDecl(frame, out string methodDecl);
+
+                    godot_stack_info* stackInfo = &vector->Elements[i];
+
+                    // Assign directly to element in Vector. This way we don't need to worry
+                    // about disposal if an exception is thrown. The Vector takes care of it.
+                    stackInfo->File = Marshaling.ConvertStringToNative(fileName);
+                    stackInfo->Func = Marshaling.ConvertStringToNative(methodDecl);
+                    stackInfo->Line = fileLineNumber;
+
+                    i++;
+                }
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugPrintUnhandledException(e);
-                ExceptionUtils.PushError("Failed to install 'System.Diagnostics.Trace' listener.");
+                ExceptionUtils.LogException(e);
             }
             }
         }
         }
 
 
-        public static void GetStackFrameInfo(StackFrame frame, out string fileName, out int fileLineNumber,
-            out string methodDecl)
+        internal static void GetStackFrameMethodDecl(StackFrame frame, out string methodDecl)
         {
         {
-            fileName = frame.GetFileName();
-            fileLineNumber = frame.GetFileLineNumber();
-
-            MethodBase methodBase = frame.GetMethod();
+            MethodBase? methodBase = frame.GetMethod();
 
 
             if (methodBase == null)
             if (methodBase == null)
             {
             {

+ 2 - 2
modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs

@@ -22,7 +22,7 @@ namespace Godot
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugUnhandledException(e);
+                ExceptionUtils.LogException(e);
                 return false.ToGodotBool();
                 return false.ToGodotBool();
             }
             }
         }
         }
@@ -58,7 +58,7 @@ namespace Godot
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugPrintUnhandledException(e);
+                ExceptionUtils.LogException(e);
                 *outRet = default;
                 *outRet = default;
             }
             }
         }
         }

+ 1 - 11
modules/mono/glue/GodotSharp/GodotSharp/Core/Dispatcher.cs

@@ -8,18 +8,8 @@ namespace Godot
     {
     {
         internal static GodotTaskScheduler DefaultGodotTaskScheduler;
         internal static GodotTaskScheduler DefaultGodotTaskScheduler;
 
 
-        [UnmanagedCallersOnly]
         internal static void InitializeDefaultGodotTaskScheduler()
         internal static void InitializeDefaultGodotTaskScheduler()
-        {
-            try
-            {
-                DefaultGodotTaskScheduler = new GodotTaskScheduler();
-            }
-            catch (Exception e)
-            {
-                ExceptionUtils.DebugUnhandledException(e);
-            }
-        }
+            => DefaultGodotTaskScheduler = new GodotTaskScheduler();
 
 
         public static GodotSynchronizationContext SynchronizationContext => DefaultGodotTaskScheduler.Context;
         public static GodotSynchronizationContext SynchronizationContext => DefaultGodotTaskScheduler.Context;
     }
     }

+ 1 - 1
modules/mono/glue/GodotSharp/GodotSharp/Core/DisposablesTracker.cs

@@ -24,7 +24,7 @@ namespace Godot
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugUnhandledException(e);
+                ExceptionUtils.LogException(e);
             }
             }
         }
         }
 
 

+ 23 - 7
modules/mono/glue/GodotSharp/GodotSharp/Core/GodotUnhandledExceptionEvent.cs

@@ -1,17 +1,33 @@
 using System;
 using System;
+using System.Runtime.InteropServices;
+using Godot.NativeInterop;
 
 
 namespace Godot
 namespace Godot
 {
 {
     public static partial class GD
     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)
+        [UnmanagedCallersOnly]
+        internal static void OnCoreApiAssemblyLoaded(godot_bool isDebug)
         {
         {
-            UnhandledException?.Invoke(null, new UnhandledExceptionArgs(e));
+            try
+            {
+                Dispatcher.InitializeDefaultGodotTaskScheduler();
+
+                if (isDebug.ToBool())
+                {
+                    DebuggingUtils.InstallTraceListener();
+
+                    AppDomain.CurrentDomain.UnhandledException += (_, e) =>
+                    {
+                        // Exception.ToString() includes the inner exception
+                        ExceptionUtils.LogUnhandledException((Exception)e.ExceptionObject);
+                    };
+                }
+            }
+            catch (Exception e)
+            {
+                ExceptionUtils.LogException(e);
+            }
         }
         }
     }
     }
 }
 }

+ 91 - 26
modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/ExceptionUtils.cs

@@ -1,4 +1,9 @@
 using System;
 using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+
+#nullable enable
 
 
 namespace Godot.NativeInterop
 namespace Godot.NativeInterop
 {
 {
@@ -10,47 +15,102 @@ namespace Godot.NativeInterop
         }
         }
 
 
         private static void OnExceptionLoggerException(Exception loggerException, Exception exceptionToLog)
         private static void OnExceptionLoggerException(Exception loggerException, Exception exceptionToLog)
-        {
-            // This better not throw
-            PushError("Exception thrown when trying to log another exception...");
-            PushError("Exception:");
-            PushError(exceptionToLog.ToString());
-            PushError("Logger exception:");
-            PushError(loggerException.ToString());
-        }
-
-        public static void DebugPrintUnhandledException(Exception e)
         {
         {
             try
             try
             {
             {
-                // TODO Not implemented (debug_print_unhandled_exception)
-                GD.PushError(e.ToString());
+                // This better not throw
+                PushError(string.Concat("Exception thrown while trying to log another exception...",
+                    "\n### Exception ###\n", exceptionToLog.ToString(),
+                    "\n### Logger exception ###\n", loggerException.ToString()));
             }
             }
-            catch (Exception unexpected)
+            catch (Exception)
             {
             {
-                OnExceptionLoggerException(unexpected, e);
+                // Well, too bad...
             }
             }
         }
         }
 
 
-        public static void DebugSendUnhandledExceptionError(Exception e)
+        private record struct StackInfoTuple(string? File, string Func, int Line);
+
+        private static void CollectExceptionInfo(Exception exception, List<StackInfoTuple> globalFrames,
+            StringBuilder excMsg)
         {
         {
-            try
+            if (excMsg.Length > 0)
+                excMsg.Append(" ---> ");
+            excMsg.Append(exception.GetType().FullName);
+            excMsg.Append(": ");
+            excMsg.Append(exception.Message);
+
+            var innerExc = exception.InnerException;
+
+            if (innerExc != null)
             {
             {
-                // TODO Not implemented (debug_send_unhandled_exception_error)
-                GD.PushError(e.ToString());
+                CollectExceptionInfo(innerExc, globalFrames, excMsg);
+                globalFrames.Add(new("", "--- End of inner exception stack trace ---", 0));
             }
             }
-            catch (Exception unexpected)
+
+            var stackTrace = new StackTrace(exception, fNeedFileInfo: true);
+
+            foreach (StackFrame frame in stackTrace.GetFrames())
             {
             {
-                OnExceptionLoggerException(unexpected, e);
+                DebuggingUtils.GetStackFrameMethodDecl(frame, out string methodDecl);
+                globalFrames.Add(new(frame.GetFileName(), methodDecl, frame.GetFileLineNumber()));
+            }
+        }
+
+        private static void SendToScriptDebugger(Exception e)
+        {
+            var globalFrames = new List<StackInfoTuple>();
+
+            var excMsg = new StringBuilder();
+
+            CollectExceptionInfo(e, globalFrames, excMsg);
+
+            string file = globalFrames.Count > 0 ? globalFrames[0].File ?? "" : "";
+            string func = globalFrames.Count > 0 ? globalFrames[0].Func : "";
+            int line = globalFrames.Count > 0 ? globalFrames[0].Line : 0;
+            string errorMsg = "Exception";
+
+            using godot_string nFile = Marshaling.ConvertStringToNative(file);
+            using godot_string nFunc = Marshaling.ConvertStringToNative(func);
+            using godot_string nErrorMsg = Marshaling.ConvertStringToNative(errorMsg);
+            using godot_string nExcMsg = Marshaling.ConvertStringToNative(excMsg.ToString());
+
+            using DebuggingUtils.godot_stack_info_vector stackInfoVector = default;
+
+            stackInfoVector.Resize(globalFrames.Count);
+
+            unsafe
+            {
+                for (int i = 0; i < globalFrames.Count; i++)
+                {
+                    DebuggingUtils.godot_stack_info* stackInfo = &stackInfoVector.Elements[i];
+
+                    var globalFrame = globalFrames[i];
+
+                    // Assign directly to element in Vector. This way we don't need to worry
+                    // about disposal if an exception is thrown. The Vector takes care of it.
+                    stackInfo->File = Marshaling.ConvertStringToNative(globalFrame.File);
+                    stackInfo->Func = Marshaling.ConvertStringToNative(globalFrame.Func);
+                    stackInfo->Line = globalFrame.Line;
+                }
+
+                NativeFuncs.godotsharp_internal_script_debugger_send_error(nFunc, nFile, line,
+                    nErrorMsg, nExcMsg, p_warning: false.ToGodotBool(), stackInfoVector);
             }
             }
         }
         }
 
 
-        public static void DebugUnhandledException(Exception e)
+        public static void LogException(Exception e)
         {
         {
             try
             try
             {
             {
-                // TODO Not implemented (debug_unhandled_exception)
-                GD.PushError(e.ToString());
+                if (NativeFuncs.godotsharp_internal_script_debugger_is_active())
+                {
+                    SendToScriptDebugger(e);
+                }
+                else
+                {
+                    GD.PushError(e.ToString());
+                }
             }
             }
             catch (Exception unexpected)
             catch (Exception unexpected)
             {
             {
@@ -58,12 +118,17 @@ namespace Godot.NativeInterop
             }
             }
         }
         }
 
 
-        public static void PrintUnhandledException(Exception e)
+        public static void LogUnhandledException(Exception e)
         {
         {
             try
             try
             {
             {
-                // TODO Not implemented (print_unhandled_exception)
-                GD.PushError(e.ToString());
+                if (NativeFuncs.godotsharp_internal_script_debugger_is_active())
+                {
+                    SendToScriptDebugger(e);
+                }
+
+                // In this case, print it as well in addition to sending it to the script debugger
+                GD.PushError("Unhandled exception\n" + e);
             }
             }
             catch (Exception unexpected)
             catch (Exception unexpected)
             {
             {

+ 19 - 1
modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs

@@ -35,6 +35,23 @@ namespace Godot.NativeInterop
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern IntPtr godotsharp_engine_get_singleton(in godot_string p_name);
         public static extern IntPtr godotsharp_engine_get_singleton(in godot_string p_name);
 
 
+
+        [DllImport(GodotDllName)]
+        internal static extern Error godotsharp_stack_info_vector_resize(
+            ref DebuggingUtils.godot_stack_info_vector p_stack_info_vector, int p_size);
+
+        [DllImport(GodotDllName)]
+        internal static extern void godotsharp_stack_info_vector_destroy(
+            ref DebuggingUtils.godot_stack_info_vector p_stack_info_vector);
+
+        [DllImport(GodotDllName)]
+        internal static extern void godotsharp_internal_script_debugger_send_error(in godot_string p_func,
+            in godot_string p_file, int p_line, in godot_string p_err, in godot_string p_descr,
+            godot_bool p_warning, in DebuggingUtils.godot_stack_info_vector p_stack_info_vector);
+
+        [DllImport(GodotDllName)]
+        internal static extern bool godotsharp_internal_script_debugger_is_active();
+
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         internal static extern IntPtr godotsharp_internal_object_get_associated_gchandle(IntPtr ptr);
         internal static extern IntPtr godotsharp_internal_object_get_associated_gchandle(IntPtr ptr);
 
 
@@ -92,7 +109,8 @@ namespace Godot.NativeInterop
             out godot_array r_output);
             out godot_array r_output);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
-        public static extern void godotsharp_ref_new_from_ref_counted_ptr(out godot_ref r_dest, IntPtr p_ref_counted_ptr);
+        public static extern void godotsharp_ref_new_from_ref_counted_ptr(out godot_ref r_dest,
+            IntPtr p_ref_counted_ptr);
 
 
         [DllImport(GodotDllName)]
         [DllImport(GodotDllName)]
         public static extern void godotsharp_ref_destroy(ref godot_ref p_instance);
         public static extern void godotsharp_ref_destroy(ref godot_ref p_instance);

+ 1 - 1
modules/mono/glue/GodotSharp/GodotSharp/Core/SignalAwaiter.cs

@@ -58,7 +58,7 @@ namespace Godot
             }
             }
             catch (Exception e)
             catch (Exception e)
             {
             {
-                ExceptionUtils.DebugPrintUnhandledException(e);
+                ExceptionUtils.LogException(e);
                 *outAwaiterIsNull = false.ToGodotBool();
                 *outAwaiterIsNull = false.ToGodotBool();
             }
             }
         }
         }

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

@@ -1,20 +0,0 @@
-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;
-        }
-    }
-}

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

@@ -8,7 +8,7 @@
     <DocumentationFile>$(OutputPath)/$(AssemblyName).xml</DocumentationFile>
     <DocumentationFile>$(OutputPath)/$(AssemblyName).xml</DocumentationFile>
     <EnableDefaultItems>false</EnableDefaultItems>
     <EnableDefaultItems>false</EnableDefaultItems>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-    <LangVersion>9</LangVersion>
+    <LangVersion>10</LangVersion>
 
 
     <AnalysisMode>Recommended</AnalysisMode>
     <AnalysisMode>Recommended</AnalysisMode>
 
 
@@ -91,7 +91,6 @@
     <Compile Include="Core\StringName.cs" />
     <Compile Include="Core\StringName.cs" />
     <Compile Include="Core\Transform2D.cs" />
     <Compile Include="Core\Transform2D.cs" />
     <Compile Include="Core\Transform3D.cs" />
     <Compile Include="Core\Transform3D.cs" />
-    <Compile Include="Core\UnhandledExceptionArgs.cs" />
     <Compile Include="Core\Vector2.cs" />
     <Compile Include="Core\Vector2.cs" />
     <Compile Include="Core\Vector2i.cs" />
     <Compile Include="Core\Vector2i.cs" />
     <Compile Include="Core\Vector3.cs" />
     <Compile Include="Core\Vector3.cs" />

+ 28 - 1
modules/mono/glue/runtime_interop.cpp

@@ -29,6 +29,8 @@
 /*************************************************************************/
 /*************************************************************************/
 
 
 #include "core/config/engine.h"
 #include "core/config/engine.h"
+#include "core/debugger/engine_debugger.h"
+#include "core/debugger/script_debugger.h"
 #include "core/io/marshalls.h"
 #include "core/io/marshalls.h"
 #include "core/object/class_db.h"
 #include "core/object/class_db.h"
 #include "core/object/method_bind.h"
 #include "core/object/method_bind.h"
@@ -81,6 +83,27 @@ GD_PINVOKE_EXPORT Object *godotsharp_engine_get_singleton(const String *p_name)
 	return Engine::get_singleton()->get_singleton_object(*p_name);
 	return Engine::get_singleton()->get_singleton_object(*p_name);
 }
 }
 
 
+GD_PINVOKE_EXPORT int32_t godotsharp_stack_info_vector_resize(
+		Vector<ScriptLanguage::StackInfo> *p_stack_info_vector, int p_size) {
+	return (int32_t)p_stack_info_vector->resize(p_size);
+}
+
+GD_PINVOKE_EXPORT void godotsharp_stack_info_vector_destroy(
+		Vector<ScriptLanguage::StackInfo> *p_stack_info_vector) {
+	p_stack_info_vector->~Vector();
+}
+
+GD_PINVOKE_EXPORT void godotsharp_internal_script_debugger_send_error(const String *p_func,
+		const String *p_file, int32_t p_line, const String *p_err, const String *p_descr,
+		bool p_warning, const Vector<ScriptLanguage::StackInfo> *p_stack_info_vector) {
+	EngineDebugger::get_script_debugger()->send_error(*p_func, *p_file, p_line, *p_err, *p_descr,
+			true, p_warning ? ERR_HANDLER_WARNING : ERR_HANDLER_ERROR, *p_stack_info_vector);
+}
+
+GD_PINVOKE_EXPORT bool godotsharp_internal_script_debugger_is_active() {
+	return EngineDebugger::is_active();
+}
+
 GD_PINVOKE_EXPORT GCHandleIntPtr godotsharp_internal_object_get_associated_gchandle(Object *p_ptr) {
 GD_PINVOKE_EXPORT GCHandleIntPtr godotsharp_internal_object_get_associated_gchandle(Object *p_ptr) {
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 	CRASH_COND(p_ptr == nullptr);
 	CRASH_COND(p_ptr == nullptr);
@@ -1288,10 +1311,14 @@ GD_PINVOKE_EXPORT void godotsharp_object_to_string(Object *p_ptr, godot_string *
 #endif
 #endif
 
 
 // We need this to prevent the functions from being stripped.
 // We need this to prevent the functions from being stripped.
-void *godotsharp_pinvoke_funcs[181] = {
+void *godotsharp_pinvoke_funcs[185] = {
 	(void *)godotsharp_method_bind_get_method,
 	(void *)godotsharp_method_bind_get_method,
 	(void *)godotsharp_get_class_constructor,
 	(void *)godotsharp_get_class_constructor,
 	(void *)godotsharp_engine_get_singleton,
 	(void *)godotsharp_engine_get_singleton,
+	(void *)godotsharp_stack_info_vector_resize,
+	(void *)godotsharp_stack_info_vector_destroy,
+	(void *)godotsharp_internal_script_debugger_send_error,
+	(void *)godotsharp_internal_script_debugger_is_active,
 	(void *)godotsharp_internal_object_get_associated_gchandle,
 	(void *)godotsharp_internal_object_get_associated_gchandle,
 	(void *)godotsharp_internal_object_disposed,
 	(void *)godotsharp_internal_object_disposed,
 	(void *)godotsharp_internal_refcounted_disposed,
 	(void *)godotsharp_internal_refcounted_disposed,

+ 6 - 24
modules/mono/mono_gd/gd_mono.cpp

@@ -360,13 +360,15 @@ static bool _on_core_api_assembly_loaded() {
 		return false;
 		return false;
 	}
 	}
 
 
-	GDMonoCache::managed_callbacks.Dispatcher_InitializeDefaultGodotTaskScheduler();
-
+	bool debug;
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
-	// Install the trace listener now before the project assembly is loaded
-	GDMonoCache::managed_callbacks.DebuggingUtils_InstallTraceListener();
+	debug = true;
+#else
+	debug = false;
 #endif
 #endif
 
 
+	GDMonoCache::managed_callbacks.GD_OnCoreApiAssemblyLoaded(debug);
+
 	return true;
 	return true;
 }
 }
 
 
@@ -534,26 +536,6 @@ Error GDMono::reload_scripts_domain() {
 #endif
 #endif
 #endif
 #endif
 
 
-#warning TODO Reimplement in C#
-#if 0
-void GDMono::unhandled_exception_hook(MonoObject *p_exc, void *) {
-	// This method will be called by the runtime when a thrown exception is not handled.
-	// It won't be called when we manually treat a thrown exception as unhandled.
-	// We assume the exception was already printed before calling this hook.
-
-#ifdef DEBUG_ENABLED
-	GDMonoUtils::debug_send_unhandled_exception_error((MonoException *)p_exc);
-	if (EngineDebugger::is_active()) {
-		EngineDebugger::get_singleton()->poll_events(false);
-	}
-#endif
-
-	exit(mono_environment_exitcode_get());
-
-	GD_UNREACHABLE();
-}
-#endif
-
 GDMono::GDMono() {
 GDMono::GDMono() {
 	singleton = this;
 	singleton = this;
 
 

+ 19 - 4
modules/mono/mono_gd/gd_mono_cache.cpp

@@ -38,8 +38,14 @@ ManagedCallbacks managed_callbacks;
 bool godot_api_cache_updated = false;
 bool godot_api_cache_updated = false;
 
 
 void update_godot_api_cache(const ManagedCallbacks &p_managed_callbacks) {
 void update_godot_api_cache(const ManagedCallbacks &p_managed_callbacks) {
-#define CHECK_CALLBACK_NOT_NULL_IMPL(m_var, m_class, m_method) ERR_FAIL_COND_MSG(m_var == nullptr, \
-		"Mono Cache: Managed callback for '" #m_class "_" #m_method "' is null.")
+	int checked_count = 0;
+
+#define CHECK_CALLBACK_NOT_NULL_IMPL(m_var, m_class, m_method)                             \
+	{                                                                                      \
+		ERR_FAIL_COND_MSG(m_var == nullptr,                                                \
+				"Mono Cache: Managed callback for '" #m_class "_" #m_method "' is null."); \
+		checked_count += 1;                                                                \
+	}
 
 
 #define CHECK_CALLBACK_NOT_NULL(m_class, m_method) CHECK_CALLBACK_NOT_NULL_IMPL(p_managed_callbacks.m_class##_##m_method, m_class, m_method)
 #define CHECK_CALLBACK_NOT_NULL(m_class, m_method) CHECK_CALLBACK_NOT_NULL_IMPL(p_managed_callbacks.m_class##_##m_method, m_class, m_method)
 
 
@@ -56,9 +62,12 @@ void update_godot_api_cache(const ManagedCallbacks &p_managed_callbacks) {
 	CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, HasScriptSignal);
 	CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, HasScriptSignal);
 	CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, ScriptIsOrInherits);
 	CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, ScriptIsOrInherits);
 	CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, AddScriptBridge);
 	CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, AddScriptBridge);
+	CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, GetOrCreateScriptBridgeForPath);
 	CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, RemoveScriptBridge);
 	CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, RemoveScriptBridge);
 	CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, UpdateScriptClassInfo);
 	CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, UpdateScriptClassInfo);
 	CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, SwapGCHandleForType);
 	CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, SwapGCHandleForType);
+	CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, GetPropertyInfoList);
+	CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, GetPropertyDefaultValues);
 	CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, Call);
 	CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, Call);
 	CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, Set);
 	CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, Set);
 	CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, Get);
 	CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, Get);
@@ -66,12 +75,18 @@ void update_godot_api_cache(const ManagedCallbacks &p_managed_callbacks) {
 	CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, CallToString);
 	CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, CallToString);
 	CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, HasMethodUnknownParams);
 	CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, HasMethodUnknownParams);
 	CHECK_CALLBACK_NOT_NULL(GCHandleBridge, FreeGCHandle);
 	CHECK_CALLBACK_NOT_NULL(GCHandleBridge, FreeGCHandle);
-	CHECK_CALLBACK_NOT_NULL(DebuggingUtils, InstallTraceListener);
-	CHECK_CALLBACK_NOT_NULL(Dispatcher, InitializeDefaultGodotTaskScheduler);
+	CHECK_CALLBACK_NOT_NULL(DebuggingUtils, GetCurrentStackInfo);
 	CHECK_CALLBACK_NOT_NULL(DisposablesTracker, OnGodotShuttingDown);
 	CHECK_CALLBACK_NOT_NULL(DisposablesTracker, OnGodotShuttingDown);
+	CHECK_CALLBACK_NOT_NULL(GD, OnCoreApiAssemblyLoaded);
 
 
 	managed_callbacks = p_managed_callbacks;
 	managed_callbacks = p_managed_callbacks;
 
 
+	// It's easy to forget to add new callbacks here, so this should help
+	if (checked_count * sizeof(void *) != sizeof(ManagedCallbacks)) {
+		int missing_count = (sizeof(ManagedCallbacks) / sizeof(void *)) - checked_count;
+		WARN_PRINT("The presence of " + itos(missing_count) + " callback(s) was not validated");
+	}
+
 	godot_api_cache_updated = true;
 	godot_api_cache_updated = true;
 }
 }
 } // namespace GDMonoCache
 } // namespace GDMonoCache

+ 4 - 4
modules/mono/mono_gd/gd_mono_cache.h

@@ -97,9 +97,9 @@ struct ManagedCallbacks {
 	using FuncCSharpInstanceBridge_CallToString = void(GD_CLR_STDCALL *)(GCHandleIntPtr, String *, bool *);
 	using FuncCSharpInstanceBridge_CallToString = void(GD_CLR_STDCALL *)(GCHandleIntPtr, String *, bool *);
 	using FuncCSharpInstanceBridge_HasMethodUnknownParams = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, const StringName *);
 	using FuncCSharpInstanceBridge_HasMethodUnknownParams = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, const StringName *);
 	using FuncGCHandleBridge_FreeGCHandle = void(GD_CLR_STDCALL *)(GCHandleIntPtr);
 	using FuncGCHandleBridge_FreeGCHandle = void(GD_CLR_STDCALL *)(GCHandleIntPtr);
-	using FuncDebuggingUtils_InstallTraceListener = void(GD_CLR_STDCALL *)();
-	using FuncDispatcher_InitializeDefaultGodotTaskScheduler = void(GD_CLR_STDCALL *)();
+	using FuncDebuggingUtils_GetCurrentStackInfo = void(GD_CLR_STDCALL *)(Vector<ScriptLanguage::StackInfo> *);
 	using FuncDisposablesTracker_OnGodotShuttingDown = void(GD_CLR_STDCALL *)();
 	using FuncDisposablesTracker_OnGodotShuttingDown = void(GD_CLR_STDCALL *)();
+	using FuncGD_OnCoreApiAssemblyLoaded = void(GD_CLR_STDCALL *)(bool);
 
 
 	FuncSignalAwaiter_SignalCallback SignalAwaiter_SignalCallback;
 	FuncSignalAwaiter_SignalCallback SignalAwaiter_SignalCallback;
 	FuncDelegateUtils_InvokeWithVariantArgs DelegateUtils_InvokeWithVariantArgs;
 	FuncDelegateUtils_InvokeWithVariantArgs DelegateUtils_InvokeWithVariantArgs;
@@ -127,9 +127,9 @@ struct ManagedCallbacks {
 	FuncCSharpInstanceBridge_CallToString CSharpInstanceBridge_CallToString;
 	FuncCSharpInstanceBridge_CallToString CSharpInstanceBridge_CallToString;
 	FuncCSharpInstanceBridge_HasMethodUnknownParams CSharpInstanceBridge_HasMethodUnknownParams;
 	FuncCSharpInstanceBridge_HasMethodUnknownParams CSharpInstanceBridge_HasMethodUnknownParams;
 	FuncGCHandleBridge_FreeGCHandle GCHandleBridge_FreeGCHandle;
 	FuncGCHandleBridge_FreeGCHandle GCHandleBridge_FreeGCHandle;
-	FuncDebuggingUtils_InstallTraceListener DebuggingUtils_InstallTraceListener;
-	FuncDispatcher_InitializeDefaultGodotTaskScheduler Dispatcher_InitializeDefaultGodotTaskScheduler;
+	FuncDebuggingUtils_GetCurrentStackInfo DebuggingUtils_GetCurrentStackInfo;
 	FuncDisposablesTracker_OnGodotShuttingDown DisposablesTracker_OnGodotShuttingDown;
 	FuncDisposablesTracker_OnGodotShuttingDown DisposablesTracker_OnGodotShuttingDown;
+	FuncGD_OnCoreApiAssemblyLoaded GD_OnCoreApiAssemblyLoaded;
 };
 };
 
 
 extern ManagedCallbacks managed_callbacks;
 extern ManagedCallbacks managed_callbacks;