summaryrefslogtreecommitdiffstats
path: root/modules/mono/mono_gd/gd_mono_utils.cpp
diff options
context:
space:
mode:
authorIgnacio Etcheverry <ignalfonsore@gmail.com>2020-01-16 17:11:13 +0100
committerIgnacio Etcheverry <ignalfonsore@gmail.com>2020-01-16 17:47:36 +0100
commitd68b9c20d69e037cff60260fe2e1fb198c62bba4 (patch)
tree716143844fa350e35d46f595c6fabf3ee1b73313 /modules/mono/mono_gd/gd_mono_utils.cpp
parentf2d45676c949782febd59cdb25674d2058291a52 (diff)
downloadredot-engine-d68b9c20d69e037cff60260fe2e1fb198c62bba4.tar.gz
Mono/C#: Script interface calls now attach the current thread
Added guards to all C# script interface calls to attach the current thread for the current scope if the thread is not already attached. This is far from ideal, as attaching the thread is not cheap and all managed thread local storage is lost when we detach the thread at the end of the calls. However, it's the best we can do for now to avoid crashing when an unattached thread tries to interact with C# code.
Diffstat (limited to 'modules/mono/mono_gd/gd_mono_utils.cpp')
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp35
1 files changed, 31 insertions, 4 deletions
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 6bb9f28a32..4e7f590a69 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -125,10 +125,12 @@ void set_main_thread(MonoThread *p_thread) {
mono_thread_set_main(p_thread);
}
-void attach_current_thread() {
- ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized());
- MonoThread *mono_thread = mono_thread_attach(mono_get_root_domain());
- ERR_FAIL_NULL(mono_thread);
+MonoThread *attach_current_thread() {
+ ERR_FAIL_COND_V(!GDMono::get_singleton()->is_runtime_initialized(), NULL);
+ MonoDomain *scripts_domain = GDMono::get_singleton()->get_scripts_domain();
+ MonoThread *mono_thread = mono_thread_attach(scripts_domain ? scripts_domain : mono_get_root_domain());
+ ERR_FAIL_NULL_V(mono_thread, NULL);
+ return mono_thread;
}
void detach_current_thread() {
@@ -138,10 +140,20 @@ void detach_current_thread() {
mono_thread_detach(mono_thread);
}
+void detach_current_thread(MonoThread *p_mono_thread) {
+ ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized());
+ ERR_FAIL_NULL(p_mono_thread);
+ mono_thread_detach(p_mono_thread);
+}
+
MonoThread *get_current_thread() {
return mono_thread_current();
}
+bool is_thread_attached() {
+ return mono_domain_get() != NULL;
+}
+
void runtime_object_init(MonoObject *p_this_obj, GDMonoClass *p_class, MonoException **r_exc) {
GDMonoMethod *ctor = p_class->get_method(".ctor", 0);
ERR_FAIL_NULL(ctor);
@@ -617,4 +629,19 @@ GDMonoClass *make_generic_dictionary_type(MonoReflectionType *p_key_reftype, Mon
} // namespace Marshal
+ScopeThreadAttach::ScopeThreadAttach() :
+ mono_thread(NULL) {
+ if (likely(GDMono::get_singleton()->is_runtime_initialized()) && unlikely(!mono_domain_get())) {
+ mono_thread = GDMonoUtils::attach_current_thread();
+ }
+}
+
+ScopeThreadAttach::~ScopeThreadAttach() {
+ if (unlikely(mono_thread)) {
+ GDMonoUtils::detach_current_thread(mono_thread);
+ }
+}
+
+// namespace Marshal
+
} // namespace GDMonoUtils