Przeglądaj źródła

Mono: Prevent raising exceptions in native code
For now we will just print the exceptions we catch. Later, we should use something similar to 'mono_set_pending_exception(ex)'.

Ignacio Etcheverry 7 lat temu
rodzic
commit
45e5e23ee8

+ 4 - 4
modules/mono/editor/bindings_generator.cpp

@@ -778,8 +778,8 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
 		cs_file.push_back(itype.proxy_name);
 		cs_file.push_back("(IntPtr " BINDINGS_PTR_FIELD ")\n" OPEN_BLOCK_L2 "this." BINDINGS_PTR_FIELD " = " BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2);
 
-		cs_file.push_back(MEMBER_BEGIN "public bool HasValidHandle()\n" OPEN_BLOCK_L2
-									   "return " BINDINGS_PTR_FIELD " == IntPtr.Zero;\n" CLOSE_BLOCK_L2);
+		cs_file.push_back(MEMBER_BEGIN "public IntPtr NativeInstance\n" OPEN_BLOCK_L2
+									   "get { return " BINDINGS_PTR_FIELD "; }\n" CLOSE_BLOCK_L2);
 	} else if (itype.is_singleton) {
 		// Add the type name and the singleton pointer as static fields
 
@@ -841,8 +841,8 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
 		// Add methods
 
 		if (!is_derived_type) {
-			cs_file.push_back(MEMBER_BEGIN "public bool HasValidHandle()\n" OPEN_BLOCK_L2
-										   "return " BINDINGS_PTR_FIELD " == IntPtr.Zero;\n" CLOSE_BLOCK_L2);
+			cs_file.push_back(MEMBER_BEGIN "public IntPtr NativeInstance\n" OPEN_BLOCK_L2
+										   "get { return " BINDINGS_PTR_FIELD "; }\n" CLOSE_BLOCK_L2);
 
 			cs_file.push_back(MEMBER_BEGIN "internal static IntPtr " CS_SMETHOD_GETINSTANCE "(Object instance)\n" OPEN_BLOCK_L2
 										   "return instance == null ? IntPtr.Zero : instance." BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2);

+ 12 - 0
modules/mono/mono_gd/gd_mono.cpp

@@ -29,6 +29,7 @@
 /*************************************************************************/
 #include "gd_mono.h"
 
+#include <mono/metadata/exception.h>
 #include <mono/metadata/mono-config.h>
 #include <mono/metadata/mono-debug.h>
 #include <mono/metadata/mono-gc.h>
@@ -47,6 +48,15 @@
 #include "../editor/godotsharp_editor.h"
 #endif
 
+void gdmono_unhandled_exception_hook(MonoObject *exc, void *user_data) {
+
+	(void)user_data; // UNUSED
+
+	ERR_PRINT(GDMonoUtils::get_exception_name_and_message(exc).utf8());
+	mono_print_unhandled_exception(exc);
+	abort();
+}
+
 #ifdef MONO_PRINT_HANDLER_ENABLED
 void gdmono_MonoPrintCallback(const char *string, mono_bool is_stdout) {
 
@@ -214,6 +224,8 @@ void GDMono::initialize() {
 	// The following assemblies are not required at initialization
 	_load_all_script_assemblies();
 
+	mono_install_unhandled_exception_hook(gdmono_unhandled_exception_hook, NULL);
+
 	OS::get_singleton()->print("Mono: ALL IS GOOD\n");
 }
 

+ 38 - 3
modules/mono/mono_gd/gd_mono_method.cpp

@@ -83,9 +83,32 @@ MonoObject *GDMonoMethod::invoke(MonoObject *p_object, const Variant **p_params,
 			mono_array_set(params, MonoObject *, i, boxed_param);
 		}
 
-		return mono_runtime_invoke_array(mono_method, p_object, params, r_exc);
+		MonoObject *exc = NULL;
+		MonoObject *ret = mono_runtime_invoke_array(mono_method, p_object, params, &exc);
+
+		if (exc) {
+			if (r_exc) {
+				*r_exc = exc;
+			} else {
+				ERR_PRINT(GDMonoUtils::get_exception_name_and_message(exc).utf8());
+				mono_print_unhandled_exception(exc);
+			}
+		}
+
+		return ret;
 	} else {
-		mono_runtime_invoke(mono_method, p_object, NULL, r_exc);
+		MonoObject *exc = NULL;
+		mono_runtime_invoke(mono_method, p_object, NULL, &exc);
+
+		if (exc) {
+			if (r_exc) {
+				*r_exc = exc;
+			} else {
+				ERR_PRINT(GDMonoUtils::get_exception_name_and_message(exc).utf8());
+				mono_print_unhandled_exception(exc);
+			}
+		}
+
 		return NULL;
 	}
 }
@@ -96,7 +119,19 @@ MonoObject *GDMonoMethod::invoke(MonoObject *p_object, MonoObject **r_exc) {
 }
 
 MonoObject *GDMonoMethod::invoke_raw(MonoObject *p_object, void **p_params, MonoObject **r_exc) {
-	return mono_runtime_invoke(mono_method, p_object, p_params, r_exc);
+	MonoObject *exc = NULL;
+	MonoObject *ret = mono_runtime_invoke(mono_method, p_object, p_params, &exc);
+
+	if (exc) {
+		if (r_exc) {
+			*r_exc = exc;
+		} else {
+			ERR_PRINT(GDMonoUtils::get_exception_name_and_message(exc).utf8());
+			mono_print_unhandled_exception(exc);
+		}
+	}
+
+	return ret;
 }
 
 bool GDMonoMethod::has_attribute(GDMonoClass *p_attr_class) {