godotengine / godot

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

Printing in the destructor of a node in the edited scene crashes the editor on exit #79506

Closed Zylann closed 1 year ago

Zylann commented 1 year ago

Godot version

Godot 4.1 e709ad4d6407e52dc62f00a471d13eb6c89f2c4c

System information

Windows 10 64 bits NVIDIA GeForce GTX 1060

Issue description

I have a print_line in the destructor of a custom class derived from Node3D. I use it in verbose mode to track when things happen. In previous versions, it worked fine. But in Godot 4.1, closing the editor crashes:

Exception has occurred: W32/0xC0000005
Unhandled exception thrown: read access violation.
this was 0xFFFFFFFFFFFFFFFF.

godot.windows.editor.dev.x86_64.exe!CowData<EditorLog::LogMessage>::_get_size() Line 81 (godot4_fork\core\templates\cowdata.h:81)
godot.windows.editor.dev.x86_64.exe!CowData<EditorLog::LogMessage>::size() Line 131 (godot4_fork\core\templates\cowdata.h:131)
godot.windows.editor.dev.x86_64.exe!Vector<EditorLog::LogMessage>::size() Line 93 (godot4_fork\core\templates\vector.h:93)
godot.windows.editor.dev.x86_64.exe!EditorLog::_process_message(const String & p_msg, EditorLog::MessageType p_type) Line 216 (godot4_fork\editor\editor_log.cpp:216)
godot.windows.editor.dev.x86_64.exe!EditorLog::add_message(const String & p_msg, EditorLog::MessageType p_type) Line 243 (godot4_fork\editor\editor_log.cpp:243)
godot.windows.editor.dev.x86_64.exe!EditorNode::_print_handler_impl(const String & p_string, bool p_error, bool p_rich) Line 6651 (godot4_fork\editor\editor_node.cpp:6651)
godot.windows.editor.dev.x86_64.exe!call_with_variant_args_static<String const &,bool,bool,0,1,2>(void(*)(const String &, bool, bool) p_method, const Variant * * p_args, Callable::CallError & r_error, IndexSequence<0,1,2> __formal) Line 777 (godot4_fork\core\variant\binder_common.h:777)
godot.windows.editor.dev.x86_64.exe!call_with_variant_args_static_ret<String const &,bool,bool>(void(*)(const String &, bool, bool) p_method, const Variant * * p_args, int p_argcount, Variant & r_ret, Callable::CallError & r_error) Line 847 (godot4_fork\core\variant\binder_common.h:847)
godot.windows.editor.dev.x86_64.exe!CallableCustomStaticMethodPointerRet<void,String const &,bool,bool>::call(const Variant * * p_arguments, int p_argcount, Variant & r_return_value, Callable::CallError & r_call_error) Line 309 (godot4_fork\core\object\callable_method_pointer.h:309)
godot.windows.editor.dev.x86_64.exe!Callable::callp(const Variant * * p_arguments, int p_argcount, Variant & r_return_value, Callable::CallError & r_call_error) Line 51 (godot4_fork\core\variant\callable.cpp:51)
godot.windows.editor.dev.x86_64.exe!CallableCustomBind::call(const Variant * * p_arguments, int p_argcount, Variant & r_return_value, Callable::CallError & r_call_error) Line 145 (godot4_fork\core\variant\callable_bind.cpp:145)
godot.windows.editor.dev.x86_64.exe!Callable::callp(const Variant * * p_arguments, int p_argcount, Variant & r_return_value, Callable::CallError & r_call_error) Line 51 (godot4_fork\core\variant\callable.cpp:51)
godot.windows.editor.dev.x86_64.exe!CallQueue::_call_function(const Callable & p_callable, const Variant * p_args, int p_argcount, bool p_show_error) Line 220 (godot4_fork\core\object\message_queue.cpp:220)
godot.windows.editor.dev.x86_64.exe!CallQueue::flush() Line 322 (godot4_fork\core\object\message_queue.cpp:322)
godot.windows.editor.dev.x86_64.exe!Main::cleanup(bool p_force) Line 3562 (godot4_fork\main\main.cpp:3562)
godot.windows.editor.dev.x86_64.exe!widechar_main(int argc, wchar_t * * argv) Line 184 (godot4_fork\platform\windows\godot_windows.cpp:184)
godot.windows.editor.dev.x86_64.exe!_main() Line 204 (godot4_fork\platform\windows\godot_windows.cpp:204)
godot.windows.editor.dev.x86_64.exe!main(int argc, char * * argv) Line 218 (godot4_fork\platform\windows\godot_windows.cpp:218)
godot.windows.editor.dev.x86_64.exe!WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * lpCmdLine, int nCmdShow) Line 232 (godot4_fork\platform\windows\godot_windows.cpp:232)
godot.windows.editor.dev.x86_64.exe!invoke_main() Line 107 (d:\a01\_work\12\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:107)
godot.windows.editor.dev.x86_64.exe!__scrt_common_main_seh() Line 288 (d:\a01\_work\12\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288)
godot.windows.editor.dev.x86_64.exe!__scrt_common_main() Line 331 (d:\a01\_work\12\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:331)
godot.windows.editor.dev.x86_64.exe!WinMainCRTStartup(void * __formal) Line 17 (d:\a01\_work\12\s\src\vctools\crt\vcstartup\src\startup\exe_winmain.cpp:17)
kernel32.dll!00007ffdcb657614() (Unknown Source:0)
ntdll.dll!00007ffdcb8c26b1() (Unknown Source:0)

Steps to reproduce

My own case is in C++, but it can be reproduced with GDScript.

Have a scene with a node having the following script on it:

@tool
extends Node3D

func _notification(what):
    if what == NOTIFICATION_PREDELETE:
        print("Destroying ", name)

Have that scene open, and close the editor.

Now unfortunately you might not notice anything depending on how your OS handles that (as with many crashes occurring on exit). I work with debug builds and that definitely makes the crash visible in the debugger. I also use the following command line to build Godot on Windows:

scons p=windows target=editor dev_build=yes warnings=all werror=yes debug_crt=yes -j4

Minimal reproduction project

PrintInNodeDestructor.zip Open the project, open the scene, then close the editor.

KoBeWi commented 1 year ago

Likely same issue as #79379

dalexeev commented 1 year ago

Maybe related:

Zylann commented 1 year ago

I don't think all of them have the same cause though. For example the first one happens in scripts specifically (while the current issue even happens in C++), does not involve closing the app and does not involve the editor.

Kiramin commented 1 year ago

Perhaps one of the above (maybe related) issues involves buffering print output somewhere it shouldnt, and it is getting stuck when it finally is forced to deal with it. I think this because my @tool script included some print statements in the _exit_tree, and every time I would delete one of those nodes in the editor, it would take longer and longer to delete the node each time (exponentially) until it eventually seemed like it was going to hang for ever. Furthermore, if I had ever deleted even a single one of these nodes, if I tried to "Reload Saved Scene" it would hang indefinitely.

All these functions worked properly when I ran the project (i.e. the code wasn't executing in tool mode).

saierXP commented 1 year ago

Maybe it was fixed by this #80161. Can you test it again? I didn't catch the crash.

KoBeWi commented 1 year ago

Fixed.