C#: Fix custom event signals crash on hot-reload

Cleanup and re-initialization of event signals before
and after hot-reload should be working correctly now.
This commit is contained in:
Ignacio Etcheverry 2020-10-26 06:59:08 +01:00
parent d5073c6b4c
commit 34960cb936
5 changed files with 19 additions and 17 deletions

View file

@ -940,8 +940,6 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
// Use a placeholder for now to avoid losing the state when saving a scene
obj->set_script(scr);
PlaceHolderScriptInstance *placeholder = scr->placeholder_instance_create(obj);
obj->set_script_instance(placeholder);
@ -968,12 +966,12 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
for (List<Ref<CSharpScript>>::Element *E = to_reload.front(); E; E = E->next()) {
Ref<CSharpScript> script = E->get();
if (!script->get_path().empty()) {
#ifdef TOOLS_ENABLED
script->exports_invalidated = true;
script->exports_invalidated = true;
#endif
script->signals_invalidated = true;
script->signals_invalidated = true;
if (!script->get_path().empty()) {
script->reload(p_soft_reload);
if (!script->valid) {
@ -1949,6 +1947,7 @@ MonoObject *CSharpInstance::_internal_new_managed() {
}
void CSharpInstance::mono_object_disposed(MonoObject *p_obj) {
// Must make sure event signals are not left dangling
disconnect_event_signals();
#ifdef DEBUG_ENABLED
@ -1964,6 +1963,9 @@ void CSharpInstance::mono_object_disposed_baseref(MonoObject *p_obj, bool p_is_f
CRASH_COND(gchandle.is_released());
#endif
// Must make sure event signals are not left dangling
disconnect_event_signals();
r_remove_script_instance = false;
if (_unreference_owner_unsafe()) {
@ -2223,6 +2225,9 @@ CSharpInstance::~CSharpInstance() {
destructing_script_instance = true;
// Must make sure event signals are not left dangling
disconnect_event_signals();
if (!gchandle.is_released()) {
if (!predelete_notified && !ref_dying) {
// This destructor is not called from the owners destructor.

View file

@ -288,7 +288,7 @@ public:
void mono_object_disposed(MonoObject *p_obj);
/*
* If 'r_delete_owner' is set to true, the caller must memdelete the script instance's owner. Otherwise, ifevent_signal
* If 'r_delete_owner' is set to true, the caller must memdelete the script instance's owner. Otherwise, if
* 'r_remove_script_instance' is set to true, the caller must destroy the script instance by removing it from its owner.
*/
void mono_object_disposed_baseref(MonoObject *p_obj, bool p_is_finalizer, bool &r_delete_owner, bool &r_remove_script_instance);

View file

@ -97,7 +97,7 @@
#define C_METHOD_MANAGED_TO_SIGNAL C_NS_MONOMARSHAL "::signal_info_to_callable"
#define C_METHOD_MANAGED_FROM_SIGNAL C_NS_MONOMARSHAL "::callable_to_signal_info"
#define BINDINGS_GENERATOR_VERSION UINT32_C(11)
#define BINDINGS_GENERATOR_VERSION UINT32_C(12)
const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN("\t%0 %1_in = %1;\n");
@ -1368,7 +1368,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
output.append(")\n" OPEN_BLOCK_L2 "if (" BINDINGS_PTR_FIELD " == IntPtr.Zero)\n" INDENT4 BINDINGS_PTR_FIELD " = ");
output.append(itype.api_type == ClassDB::API_EDITOR ? BINDINGS_CLASS_NATIVECALLS_EDITOR : BINDINGS_CLASS_NATIVECALLS);
output.append("." + ctor_method);
output.append("(this);\n" CLOSE_BLOCK_L2);
output.append("(this);\n" INDENT3 "_InitializeGodotScriptInstanceInternals();\n" CLOSE_BLOCK_L2);
} else {
// Hide the constructor
output.append(MEMBER_BEGIN "internal ");

View file

@ -15,14 +15,13 @@ namespace Godot
public Object() : this(false)
{
if (ptr == IntPtr.Zero)
{
ptr = godot_icall_Object_Ctor(this);
}
else
{
// This is called inside godot_icall_Object_Ctor, so we must call it as well in this case.
godot_icall_Object_ConnectEventSignals(ptr);
}
_InitializeGodotScriptInstanceInternals();
}
internal void _InitializeGodotScriptInstanceInternals()
{
godot_icall_Object_ConnectEventSignals(ptr);
}
internal Object(bool memoryOwn)

View file

@ -109,8 +109,6 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
CSharpInstance *csharp_instance = CSharpInstance::create_for_managed_type(unmanaged, script.ptr(), gchandle);
unmanaged->set_script_and_instance(script, csharp_instance);
csharp_instance->connect_event_signals();
}
void unhandled_exception(MonoException *p_exc) {