summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorPedro J. Estébanez <pedrojrulez@gmail.com>2020-05-06 14:19:01 +0200
committerPedro J. Estébanez <pedrojrulez@gmail.com>2020-06-10 20:44:11 +0200
commit4e4b1d7568fd5a98df69e363f34e48c6dd6ddae8 (patch)
treee478476e07873296062880098f865e7fa70bd71d /core
parentcb3ca99b136b8b51db663896e6391fecd9931033 (diff)
Fix potential crash when listing leaked objects
Note: Casting to the C++ classes and calling the methods there would work as well, but would require including he header files for the specific object types handled here, which wouldn't be OK either.
Diffstat (limited to 'core')
-rw-r--r--core/object.cpp15
1 files changed, 11 insertions, 4 deletions
diff --git a/core/object.cpp b/core/object.cpp
index 3ea3e27d41..8abea9ca7e 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -2040,20 +2040,27 @@ void ObjectDB::cleanup() {
WARN_PRINT("ObjectDB instances leaked at exit (run with --verbose for details).");
if (OS::get_singleton()->is_stdout_verbose()) {
+ // Ensure calling the native classes because if a leaked instance has a script
+ // that overrides any of those methods, it'd not be OK to call them at this point,
+ // now the scripting languages have already been terminated.
+ MethodBind *node_get_name = ClassDB::get_method("Node", "get_name");
+ MethodBind *resource_get_path = ClassDB::get_method("Resource", "get_path");
+ Callable::CallError call_error;
+
for (uint32_t i = 0; i < slot_count; i++) {
uint32_t slot = object_slots[i].next_free;
Object *obj = object_slots[slot].object;
- String node_name;
+ String extra_info;
if (obj->is_class("Node")) {
- node_name = " - Node name: " + String(obj->call("get_name"));
+ extra_info = " - Node name: " + String(node_get_name->call(obj, nullptr, 0, call_error));
}
if (obj->is_class("Resource")) {
- node_name = " - Resource path: " + String(obj->call("get_path"));
+ extra_info = " - Resource path: " + String(resource_get_path->call(obj, nullptr, 0, call_error));
}
uint64_t id = uint64_t(slot) | (uint64_t(object_slots[slot].validator) << OBJECTDB_VALIDATOR_BITS) | (object_slots[slot].is_reference ? OBJECTDB_REFERENCE_BIT : 0);
- print_line("Leaked instance: " + String(obj->get_class()) + ":" + itos(id) + node_name);
+ print_line("Leaked instance: " + String(obj->get_class()) + ":" + itos(id) + extra_info);
}
print_line("Hint: Leaked instances typically happen when nodes are removed from the scene tree (with `remove_child()`) but not freed (with `free()` or `queue_free()`).");
}