I'm trying to debug an issue where a certain type of node can't be freed at the intended time because it is 'locked' (Attempted to free a locked object (calling or emitting)). However, I don't know what 'locked' really means and I can't find a precise definition anywhere, so I'm asking here.
When is a node unable to be freed?
You almost never want to call free directly. I would recommend using queue_free, which will free the object at some later point when it is safe to do so. You should also use remove_child first (before calling queue_free) so that it will disappear from the screen and stop updating while it is getting ready to be freed.
I actually had queue_free() in the code at first, but it removed the node 'too late'. The intended functionality was: First child of a node is queue_free()'d New node is instanced and added as child (replacing the above) Method is called on new node However, what actually happens is: Method gets called on the first node, probably because it hasn't been freed yet I randomly changed it to free() which made it work fine so I kept going (only for free() to cause the 'locked' issue later when i added a different type of node that goes through the same process.)
In hindsight, there isn't actually any need for the node to be freed instantly. Like you say, just using remove_child() to 'get it out of the way' when needed, and having queue_free() clean it up later, would be way better. I am still curious about when a node is 'locked' though, as the node that had that issue really did not seem like it would be executing anything when free() was called on it.
- Edited
It probably means you kept a reference to the node that was freed and were doing something with it. The fact the the method got called on the first node proves that (as functions don't call themselves, the computer only does what you tell it). So look to see if you saved a variable for the node you wish to free and make sure that it is either set to null (after you remove_child and queue_free) or that it is immediately set to the new node if that happens in the same place.
Just to add: A node being locked can also mean another Godot node or system has a reference to it. This is often the case with physics-based nodes (RigidBody2D, KinematicBody2D, etc) since the physics engine relies on them, which makes it where you almost always have to remove them with queue_free
.
However, if it's a non-physics node then its probably a code reference that is causing the issue.
- Edited
@toughbrook said: 'locked' (Attempted to free a locked object (calling or emitting)).
The message is self-explanatory really. You tried to delete the object while that object is in the middle of a function call (or emit, which is basically just a function call). The object is locked during a call so that execution can safely return to the caller. Otherwise you'll end up with invalid object context to return to and no other option but to throw an exception. So in your case, the execution probably got tangled a bit and object called another object's method that directly or indirectly tried to delete the caller object.
For experimentation sake, you can easily replicate this: - make a scene with two sibling nodes - define a function in node1 that deletes node2 using free() - call that function from node2
queue_free() is safe precisely because it ensures that stuff like this can never happen as deletion will occur only after all scripts for the current frame have been fully executed.