godot icon indicating copy to clipboard operation
godot copied to clipboard

Cleanup function state connections when destroying instance

Open KoBeWi opened this issue 3 years ago • 2 comments

Closes #24311

It can't be that simple, can it? 🤔

KoBeWi avatar Sep 16 '22 15:09 KoBeWi

I rebased and the code is not valid anymore :/ It works, but sanitizer is not happy about it.

KoBeWi avatar Nov 27 '22 22:11 KoBeWi

I suspect that the same GDScriptInstance::~GDScriptInstance() is ran twice. Try adding a destructing variable, like I did in GDScript::~GDScript().

adamscott avatar Nov 28 '22 15:11 adamscott

I suspect that the same GDScriptInstance::~GDScriptInstance() is ran twice. Try adding a destructing variable, like I did in GDScript::~GDScript().

Curious to know how that would happen. I figured destructors would only ever run once!

anvilfolk avatar Nov 28 '22 18:11 anvilfolk

I just tested adding destructing to GDScriptInstance but the issues persist unfortunately.

anvilfolk avatar Nov 28 '22 21:11 anvilfolk

This patch makes the build pass the sanitizer.

diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 72d5bb23c5..dc87560fdd 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -1925,10 +1925,14 @@ GDScriptInstance::~GDScriptInstance() {
 
 	while (SelfList<GDScriptFunctionState> *E = pending_func_states.first()) {
 		// Order matters since clearing the stack may already cause
-		// the GDSCriptFunctionState to be destroyed and thus removed from the list.
+		// the GDScriptFunctionState to be destroyed and thus removed from the list.
 		pending_func_states.remove(E);
-		E->self()->_clear_connections();
-		E->self()->_clear_stack();
+		GDScriptFunctionState *state = E->self();
+		state->_clear_connections();
+		state = Object::cast_to<GDScriptFunctionState>(state);
+		if (state != nullptr) {
+			state->_clear_stack();
+		}
 	}
 
 	if (script.is_valid() && owner) {

adamscott avatar Nov 30 '22 01:11 adamscott

Weird. My local build pass the clang test sanitizers.

adamscott avatar Nov 30 '22 14:11 adamscott

My hunch says that this is more sane than casting AND it should fix the macos SIGSEGV.

diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index df57749f76..fc3d42b1b0 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -1484,9 +1484,9 @@ GDScript::~GDScript() {
 			// the GDScriptFunctionState to be destroyed and thus removed from the list.
 			pending_func_states.remove(E);
 			GDScriptFunctionState *state = E->self();
+			ObjectID state_id = state->get_instance_id();
 			state->_clear_connections();
-			state = Object::cast_to<GDScriptFunctionState>(state);
-			if (state != nullptr) {
+			if (ObjectDB::get_instance(state_id) != nullptr) {
 				state->_clear_stack();
 			}
 		}
@@ -1932,9 +1932,9 @@ GDScriptInstance::~GDScriptInstance() {
 		// the GDSCriptFunctionState to be destroyed and thus removed from the list.
 		pending_func_states.remove(E);
 		GDScriptFunctionState *state = E->self();
+		ObjectID state_id = state->get_instance_id();
 		state->_clear_connections();
-		state = Object::cast_to<GDScriptFunctionState>(state);
-		if (state != nullptr) {
+		if (ObjectDB::get_instance(state_id) != nullptr) {
 			state->_clear_stack();
 		}
 	}

adamscott avatar Dec 01 '22 23:12 adamscott

Thanks!

akien-mga avatar Feb 03 '23 15:02 akien-mga