godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.21k stars 21.04k forks source link

Crash while saving after running tool. #73786

Open prominentdetail opened 1 year ago

prominentdetail commented 1 year ago

Godot version

4.0 rc3

System information

windows 10

Issue description

Crashes while saving after running tool on node.

Steps to reproduce

run "fillArrayTool.gd" on the "runToolOnMe" node (must have node selected). Save afterwards.

Minimal reproduction project

saveCrashBug.zip

akien-mga commented 1 year ago

That's an infinite recursion, you're filling dictionaries with references to each other.

ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)
ERROR: Max recursion reached
   at: recursive_hash (core/variant/dictionary.cpp:260)

Thread 1 "godot-git" received signal SIGSEGV, Segmentation fault.
0x000000000a13a6d0 in Variant::hash_compare (this=<error reading variable: Cannot access memory at address 0x7fffff7fefd8>, p_variant=<error reading variable: Cannot access memory at address 0x7fffff7fefd0>, recursion_count=<error reading variable: Cannot access memory at address 0x7fffff7fefcc>) at core/variant/variant.cpp:3289
3289    bool Variant::hash_compare(const Variant &p_variant, int recursion_count) const {

(gdb) bt
#0  0x000000000a13a6d0 in Variant::hash_compare (this=<error reading variable: Cannot access memory at address 0x7fffff7fefd8>, 
    p_variant=<error reading variable: Cannot access memory at address 0x7fffff7fefd0>, recursion_count=<error reading variable: Cannot access memory at address 0x7fffff7fefcc>) at core/variant/variant.cpp:3289
#1  0x000000000a13d487 in StringLikeVariantComparator::compare (p_lhs=..., p_rhs=...) at core/variant/variant.cpp:3536
#2  0x000000000a12ec7a in HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator, DefaultTypedAllocator<HashMapElement<Variant, Variant> > >::_lookup_pos (this=0x1dd22370, p_key=..., 
    r_pos=@0x7fffff7ff48c: 0) at ./core/templates/hash_map.h:119
#3  0x000000000a12e40d in HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator, DefaultTypedAllocator<HashMapElement<Variant, Variant> > >::operator[] (this=0x1dd22370, p_key=...)
    at ./core/templates/hash_map.h:510
#4  0x000000000a12cdbb in Dictionary::operator[] (this=0x7fffff7ff5d0, p_key=...) at core/variant/dictionary.cpp:97
#5  0x0000000008ff3dba in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1939
#6  0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#7  0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#8  0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#9  0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#10 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#11 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#12 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#13 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#14 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#15 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#16 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#17 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#18 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#19 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#20 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#21 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#22 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#23 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#24 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940

...

#20093 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#20094 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#20095 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#20096 0x0000000008ff3cd9 in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1927
#20097 0x0000000008ff3cd9 in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1927
#20098 0x0000000008ff3ded in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=false) at scene/resources/resource_format_text.cpp:1940
#20099 0x0000000008ff3bc9 in ResourceFormatSaverTextInstance::_find_resources (this=0x7fffffff8e90, p_variant=..., p_main=true) at scene/resources/resource_format_text.cpp:1911
#20100 0x0000000008ff4354 in ResourceFormatSaverTextInstance::save (this=0x7fffffff8e90, p_path=..., p_resource=..., p_flags=96) at scene/resources/resource_format_text.cpp:1978
#20101 0x0000000008ffa020 in ResourceFormatSaverText::save (this=0xd8c7510, p_resource=..., p_path=..., p_flags=96) at scene/resources/resource_format_text.cpp:2372
#20102 0x000000000a07800b in ResourceSaver::save (p_resource=..., p_path=..., p_flags=96) at core/io/resource_saver.cpp:128
#20103 0x00000000075406e1 in EditorNode::_save_scene (this=0xe5cddb0, p_file=..., idx=-1) at editor/editor_node.cpp:1776
#20104 0x000000000753f5da in EditorNode::_save_scene_with_preview (this=0xe5cddb0, p_file=..., p_idx=-1) at editor/editor_node.cpp:1639
#20105 0x000000000754ae62 in EditorNode::_menu_option_confirm (this=0xe5cddb0, p_option=3, p_confirmed=false) at editor/editor_node.cpp:2710
#20106 0x000000000753c295 in EditorNode::_menu_option (this=0xe5cddb0, p_option=3) at editor/editor_node.cpp:1350
#20107 0x00000000075ba07d in call_with_variant_args_helper<EditorNode, int, 0ul> (p_instance=0xe5cddb0, p_method=(void (EditorNode::*)(EditorNode * const, int)) 0x753c270 <EditorNode::_menu_option(int)>, p_args=0x7fffffffa140, r_error=...) at ./core/variant/binder_common.h:293
#20108 0x00000000075b8d3c in call_with_variant_args<EditorNode, int> (p_instance=0xe5cddb0, p_method=(void (EditorNode::*)(EditorNode * const, int)) 0x753c270 <EditorNode::_menu_option(int)>, p_args=0x7fffffffa140, p_argcount=1, r_error=...) at ./core/variant/binder_common.h:407
#20109 0x00000000075b7a46 in CallableCustomMethodPointer<EditorNode, int>::call (this=0x1646bac0, p_arguments=0x7fffffffa140, p_argcount=1, r_return_value=..., r_call_error=...) at ./core/object/callable_method_pointer.h:104
#20110 0x000000000a128879 in Callable::callp (this=0x23721708, p_arguments=0x7fffffffa140, p_argcount=1, r_return_value=..., r_call_error=...) at core/variant/callable.cpp:50
#20111 0x000000000a45e74e in Object::emit_signalp (this=0x102ca8e0, p_name=..., p_args=0x7fffffffa140, p_argcount=1) at core/object/object.cpp:1046
#20112 0x0000000005d5c0a5 in Object::emit_signal<int> (this=0x102ca8e0, p_name=...) at ./core/object/object.h:869
#20113 0x0000000008649c48 in PopupMenu::activate_item (this=0x102ca8e0, p_item=6) at scene/gui/popup_menu.cpp:1718
#20114 0x000000000864963c in PopupMenu::activate_item_by_event (this=0x102ca8e0, p_event=..., p_for_global_only=false) at scene/gui/popup_menu.cpp:1644
#20115 0x0000000008613685 in MenuBar::shortcut_input (this=0x102c7e00, p_event=...) at scene/gui/menu_bar.cpp:166
#20116 0x00000000083a8bc5 in Node::_call_shortcut_input (this=0x102c7e00, p_event=...) at scene/main/node.cpp:2779
#20117 0x00000000083d529f in SceneTree::_call_input_pause (this=0xe4f1240, p_group=..., p_call_type=SceneTree::CALL_INPUT_TYPE_SHORTCUT_INPUT, p_input=..., p_viewport=0xe4ee330) at scene/main/scene_tree.cpp:956
#20118 0x0000000008408b62 in Viewport::push_unhandled_input (this=0xe4ee330, p_event=..., p_local_coords=false) at scene/main/viewport.cpp:2865
#20119 0x000000000844b9ff in Window::_window_input (this=0xe4ee330, p_ev=...) at scene/main/window.cpp:1370
#20120 0x0000000008479890 in call_with_variant_args_helper<Window, Ref<InputEvent> const&, 0ul> (p_instance=0xe4ee330, p_method=(void (Window::*)(Window * const, const Ref<InputEvent> &)) 0x844b5d0 <Window::_window_input(Ref<InputEvent> const&)>, p_args=0x7fffffffc8b8, r_error=...) at ./core/variant/binder_common.h:293
#20121 0x0000000008476387 in call_with_variant_args<Window, Ref<InputEvent> const&> (p_instance=0xe4ee330, p_method=(void (Window::*)(Window * const, const Ref<InputEvent> &)) 0x844b5d0 <Window::_window_input(Ref<InputEvent> const&)>, p_args=0x7fffffffc8b8, p_argcount=1, r_error=...) at ./core/variant/binder_common.h:407
#20122 0x0000000008472400 in CallableCustomMethodPointer<Window, Ref<InputEvent> const&>::call (this=0xe4e2d20, p_arguments=0x7fffffffc8b8, p_argcount=1, r_return_value=..., r_call_error=...) at ./core/object/callable_method_pointer.h:104
#20123 0x000000000a128879 in Callable::callp (this=0x7fffffffc860, p_arguments=0x7fffffffc8b8, p_argcount=1, r_return_value=..., r_call_error=...) at core/variant/callable.cpp:50
#20124 0x00000000052b7611 in DisplayServerX11::_dispatch_input_event (this=0xc2badd0, p_event=...) at platform/linuxbsd/x11/display_server_x11.cpp:3570
#20125 0x00000000052b7389 in DisplayServerX11::_dispatch_input_events (p_event=...) at platform/linuxbsd/x11/display_server_x11.cpp:3541
#20126 0x000000000a0c7c79 in Input::_parse_input_event_impl (this=0xbc311e0, p_event=..., p_is_emulated=false) at core/input/input.cpp:690
#20127 0x000000000a0c9082 in Input::flush_buffered_events (this=0xbc311e0) at core/input/input.cpp:940
#20128 0x00000000052bc33d in DisplayServerX11::process_events (this=0xc2badd0) at platform/linuxbsd/x11/display_server_x11.cpp:4638
#20129 0x000000000529bd6e in OS_LinuxBSD::run (this=0x7fffffffd190) at platform/linuxbsd/os_linuxbsd.cpp:876
#20130 0x0000000005293240 in main (argc=2, argv=0x7fffffffd6f8) at platform/linuxbsd/godot_linuxbsd.cpp:73

Somehow the guards again stack overflow in dictionary which raise errors don't stop the process of saving the resource.

prominentdetail commented 1 year ago

Ah, does that mean it should work/be supported? Because being able to reference each other is really useful, and I thought it would work considering the editor lists the data when you inspect it.

akien-mga commented 1 year ago

It's not supported no, if dictionary A contains dictionary B, which contains dictionary A, that's a circular / infinite reference and will always lead to either a stack overflow, or hitting an arbitrary limit put in place to detect circular references and abort before crashing.

prominentdetail commented 1 year ago

Is there a way to just store the reference though, not the whole dictionary? I basically just want to point to it so that it is easy to create a relationship tree between a ton of dictionaries so that I can easily traverse amongst them without storing indices and editing indices if a dictionary is removed, etc. I guess I just don't understand why it has to recreate the dictionaries if I just want to save pointers essentially to the dictionaries.

I mean, technically it works, since you can create them via code- but the problem is saving it. It should just store a reference, not the actual data of those references recursively.

akien-mga commented 1 year ago

When you save to a file, the format we use has no concept for references to another dictionary. All the values need to be written out by value so they can be deserialized when loading from text.

prominentdetail commented 1 year ago

Okay, thanks for the info. I guess I'll just store the indices of the array where each dictionary is located then.