|
@@ -31,6 +31,7 @@
|
|
|
#include "gd_mono_utils.h"
|
|
|
|
|
|
#include "os/dir_access.h"
|
|
|
+#include "os/os.h"
|
|
|
#include "project_settings.h"
|
|
|
#include "reference.h"
|
|
|
|
|
@@ -53,6 +54,7 @@ MonoCache mono_cache;
|
|
|
#define CACHE_NS_CLASS_AND_CHECK(m_ns, m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.class_##m_ns##_##m_class, m_val)
|
|
|
#define CACHE_RAW_MONO_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.rawclass_##m_class, m_val)
|
|
|
#define CACHE_FIELD_AND_CHECK(m_class, m_field, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.field_##m_class##_##m_field, m_val)
|
|
|
+#define CACHE_METHOD_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.method_##m_class##_##m_method, m_val)
|
|
|
#define CACHE_METHOD_THUNK_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.methodthunk_##m_class##_##m_method, m_val)
|
|
|
|
|
|
void MonoCache::clear_members() {
|
|
@@ -72,6 +74,13 @@ void MonoCache::clear_members() {
|
|
|
class_String = NULL;
|
|
|
class_IntPtr = NULL;
|
|
|
|
|
|
+#ifdef DEBUG_ENABLED
|
|
|
+ class_System_Diagnostics_StackTrace = NULL;
|
|
|
+ methodthunk_System_Diagnostics_StackTrace_GetFrames = NULL;
|
|
|
+ method_System_Diagnostics_StackTrace_ctor_bool = NULL;
|
|
|
+ method_System_Diagnostics_StackTrace_ctor_Exception_bool = NULL;
|
|
|
+#endif
|
|
|
+
|
|
|
rawclass_Dictionary = NULL;
|
|
|
|
|
|
class_Vector2 = NULL;
|
|
@@ -94,6 +103,11 @@ void MonoCache::clear_members() {
|
|
|
class_WeakRef = NULL;
|
|
|
class_MarshalUtils = NULL;
|
|
|
|
|
|
+#ifdef DEBUG_ENABLED
|
|
|
+ class_DebuggingUtils = NULL;
|
|
|
+ methodthunk_DebuggingUtils_GetStackFrameInfo = NULL;
|
|
|
+#endif
|
|
|
+
|
|
|
class_ExportAttribute = NULL;
|
|
|
field_ExportAttribute_hint = NULL;
|
|
|
field_ExportAttribute_hintString = NULL;
|
|
@@ -137,6 +151,13 @@ void update_corlib_cache() {
|
|
|
CACHE_CLASS_AND_CHECK(double, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_double_class()));
|
|
|
CACHE_CLASS_AND_CHECK(String, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_string_class()));
|
|
|
CACHE_CLASS_AND_CHECK(IntPtr, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_intptr_class()));
|
|
|
+
|
|
|
+#ifdef DEBUG_ENABLED
|
|
|
+ CACHE_CLASS_AND_CHECK(System_Diagnostics_StackTrace, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Diagnostics", "StackTrace"));
|
|
|
+ CACHE_METHOD_THUNK_AND_CHECK(System_Diagnostics_StackTrace, GetFrames, (StackTrace_GetFrames)CACHED_CLASS(System_Diagnostics_StackTrace)->get_method("GetFrames")->get_thunk());
|
|
|
+ CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(bool)", true));
|
|
|
+ CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_Exception_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(System.Exception,bool)", true));
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
void update_godot_api_cache() {
|
|
@@ -161,6 +182,10 @@ void update_godot_api_cache() {
|
|
|
CACHE_CLASS_AND_CHECK(WeakRef, GODOT_API_CLASS(WeakRef));
|
|
|
CACHE_CLASS_AND_CHECK(MarshalUtils, GODOT_API_CLASS(MarshalUtils));
|
|
|
|
|
|
+#ifdef DEBUG_ENABLED
|
|
|
+ CACHE_CLASS_AND_CHECK(DebuggingUtils, GODOT_API_CLASS(DebuggingUtils));
|
|
|
+#endif
|
|
|
+
|
|
|
// Attributes
|
|
|
CACHE_CLASS_AND_CHECK(ExportAttribute, GODOT_API_CLASS(ExportAttribute));
|
|
|
CACHE_FIELD_AND_CHECK(ExportAttribute, hint, CACHED_CLASS(ExportAttribute)->get_field("hint"));
|
|
@@ -183,6 +208,10 @@ void update_godot_api_cache() {
|
|
|
CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, FailureCallback, (SignalAwaiter_FailureCallback)GODOT_API_CLASS(SignalAwaiter)->get_method("FailureCallback", 0)->get_thunk());
|
|
|
CACHE_METHOD_THUNK_AND_CHECK(GodotTaskScheduler, Activate, (GodotTaskScheduler_Activate)GODOT_API_CLASS(GodotTaskScheduler)->get_method("Activate", 0)->get_thunk());
|
|
|
|
|
|
+#ifdef DEBUG_ENABLED
|
|
|
+ CACHE_METHOD_THUNK_AND_CHECK(DebuggingUtils, GetStackFrameInfo, (DebugUtils_StackFrameInfo)GODOT_API_CLASS(DebuggingUtils)->get_method("GetStackFrameInfo", 4)->get_thunk());
|
|
|
+#endif
|
|
|
+
|
|
|
{
|
|
|
/*
|
|
|
* TODO Right now we only support Dictionary<object, object>.
|
|
@@ -366,9 +395,47 @@ String get_exception_name_and_message(MonoObject *p_ex) {
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
-void print_unhandled_exception(MonoObject *p_ex) {
|
|
|
- ERR_PRINT(GDMonoUtils::get_exception_name_and_message(p_ex).utf8());
|
|
|
- mono_print_unhandled_exception(p_ex);
|
|
|
+void print_unhandled_exception(MonoObject *p_exc) {
|
|
|
+ print_unhandled_exception(p_exc, false);
|
|
|
+}
|
|
|
+
|
|
|
+void print_unhandled_exception(MonoObject *p_exc, bool p_fail_silently) {
|
|
|
+ mono_print_unhandled_exception(p_exc);
|
|
|
+#ifdef DEBUG_ENABLED
|
|
|
+ GDMonoClass *st_klass = CACHED_CLASS(System_Diagnostics_StackTrace);
|
|
|
+ MonoObject *stack_trace = mono_object_new(mono_domain_get(), st_klass->get_mono_ptr());
|
|
|
+
|
|
|
+ MonoBoolean need_file_info = true;
|
|
|
+ void *ctor_args[2] = { p_exc, &need_file_info };
|
|
|
+
|
|
|
+ MonoObject *unexpected_exc = NULL;
|
|
|
+ CACHED_METHOD(System_Diagnostics_StackTrace, ctor_Exception_bool)->invoke_raw(stack_trace, ctor_args, &unexpected_exc);
|
|
|
+
|
|
|
+ if (unexpected_exc != NULL) {
|
|
|
+ mono_print_unhandled_exception(unexpected_exc);
|
|
|
+
|
|
|
+ if (p_fail_silently) {
|
|
|
+ // Called from CSharpLanguage::get_current_stack_info,
|
|
|
+ // so printing an error here could result in endless recursion
|
|
|
+ OS::get_singleton()->printerr("Mono: Method GDMonoUtils::print_unhandled_exception failed");
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ ERR_FAIL();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Vector<ScriptLanguage::StackInfo> si;
|
|
|
+ if (stack_trace != NULL)
|
|
|
+ si = CSharpLanguage::get_singleton()->stack_trace_get_info(stack_trace);
|
|
|
+
|
|
|
+ String file = si.size() ? si[0].file : __FILE__;
|
|
|
+ String func = si.size() ? si[0].func : FUNCTION_STR;
|
|
|
+ int line = si.size() ? si[0].line : __LINE__;
|
|
|
+ String error_msg = "Unhandled exception";
|
|
|
+ String exc_msg = GDMonoUtils::get_exception_name_and_message(p_exc);
|
|
|
+
|
|
|
+ ScriptDebugger::get_singleton()->send_error(func, file, line, error_msg, exc_msg, ERR_HANDLER_ERROR, si);
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
} // namespace GDMonoUtils
|