From b271aa48e4e0af3d9abb998ac9c03eae3b65825a Mon Sep 17 00:00:00 2001 From: Ignacio Etcheverry Date: Sun, 31 Dec 2017 22:37:57 +0100 Subject: Mono: Script lifetime fixes - alloc_language_binding: Use strong GC handle as well for references. Fixes #15138 - Set the native instance field of Godot.Object to IntPtr.Zero when it's freed. - Create weak handles without tracking resurrection (that was causing trouble). This means we have to call notification predelete before queueing a native Object for deletion, and use the MonoObject* passed by the finalizer because the weak GC handle target will return NULL at this point. --- modules/mono/mono_gd/gd_mono.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'modules/mono/mono_gd/gd_mono.cpp') diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index c997b0f000..08059c9ba9 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -703,7 +703,7 @@ bool _GodotSharp::is_domain_loaded() { call_deferred("_dispose_callback"); \ } -void _GodotSharp::queue_dispose(Object *p_object) { +void _GodotSharp::queue_dispose(MonoObject *p_mono_object, Object *p_object) { if (GDMonoUtils::is_main_thread() && !GDMono::get_singleton()->is_finalizing_scripts_domain()) { _dispose_object(p_object); @@ -712,6 +712,13 @@ void _GodotSharp::queue_dispose(Object *p_object) { queue_mutex->lock(); #endif + // This is our last chance to invoke notification predelete (this is being called from the finalizer) + // We must use the MonoObject* passed by the finalizer, because the weak GC handle target returns NULL at this point + CSharpInstance *si = CAST_CSHARP_INSTANCE(p_object->get_script_instance()); + if (si) { + si->call_notification_no_check(p_mono_object, Object::NOTIFICATION_PREDELETE); + } + ENQUEUE_FOR_DISPOSAL(obj_delete_queue, p_object); #ifndef NO_THREADS -- cgit v1.2.3