diff options
author | Juan Linietsky <reduzio@gmail.com> | 2023-01-07 12:12:24 +0100 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2023-01-07 12:57:24 +0100 |
commit | 398e73c689e8506933a066c6a8045a50f58d0c04 (patch) | |
tree | 2aabcc715a855e97d560cef51902e18b3e83c65f /scene/main/node.cpp | |
parent | 163f6f5fe87d11645e94cd49f41226ab03063e53 (diff) | |
download | redot-engine-398e73c689e8506933a066c6a8045a50f58d0c04.tar.gz |
Error when removing a phycics node during a physics callback
* This behavior is not allowed, the error text suggests using call_deferred().
* Added a check in Node::remove_child to prevent future crashes of this type.
* Fixed a performance regression introduced by #36244.
Fixes #63718, probably other crashes too.
Diffstat (limited to 'scene/main/node.cpp')
-rw-r--r-- | scene/main/node.cpp | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 8f173e4c0d..177c8a3bc9 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -278,7 +278,10 @@ void Node::_propagate_exit_tree() { //block while removing children #ifdef DEBUG_ENABLED - SceneDebugger::remove_from_cache(data.scene_file_path, this); + if (!data.scene_file_path.is_empty()) { + // Only remove if file path is set (optimization). + SceneDebugger::remove_from_cache(data.scene_file_path, this); + } #endif data.blocked++; @@ -304,7 +307,6 @@ void Node::_propagate_exit_tree() { } // exit groups - for (KeyValue<StringName, GroupData> &E : data.grouped) { data.tree->remove_from_group(E.key, this); E.value.group = nullptr; @@ -1165,7 +1167,7 @@ void Node::add_sibling(Node *p_sibling, bool p_force_readable_name) { void Node::remove_child(Node *p_child) { ERR_FAIL_NULL(p_child); - ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, `remove_child()` failed. Consider using `remove_child.call_deferred(child)` instead."); + ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy adding/removing children, `remove_child()` can't be called at this time. Consider using `remove_child.call_deferred(child)` instead."); int child_count = data.children.size(); Node **children = data.children.ptrw(); @@ -1196,11 +1198,13 @@ void Node::remove_child(Node *p_child) { data.internal_children_back--; } + data.blocked++; p_child->_set_tree(nullptr); //} remove_child_notify(p_child); p_child->notification(NOTIFICATION_UNPARENTED); + data.blocked--; data.children.remove_at(idx); |