Repository: godot
Issue: Using `print_line` from `RenderingDeviceVulkan::free()` crashes the editor on exit
Labels: bug,discussion,topic:core,usability

### Godot version

Godot 4 f3c68d6c8312b0847a9083f1989c39c7453f9665

### System information

Windows 10 64 bits NVIDIA GeForce GTX 1060

### Issue description

The editor crashes with the following call stack:

```
Unhandled exception thrown: read access violation.
this: 0x000002c053d18788 {_ptr=0xdddddddddddddddd {text={_cowdata={_ptr=??? } } type=??? count=??? } }

CowData<EditorLog::LogMessage>::size() Line 133 (godot4_fork\core\templates\cowdata.h:133)
Vector<EditorLog::LogMessage>::size() Line 90 (godot4_fork\core\templates\vector.h:90)
EditorLog::_process_message(const String & p_msg, EditorLog::MessageType p_type) Line 209 (godot4_fork\editor\editor_log.cpp:209)
EditorLog::add_message(const String & p_msg, EditorLog::MessageType p_type) Line 236 (godot4_fork\editor\editor_log.cpp:236)
EditorNode::_print_handler(void * p_this, const String & p_string, bool p_error, bool p_rich) Line 5945 (godot4_fork\editor\editor_node.cpp:5945)
__print_line(String p_string) Line 82 (godot4_fork\core\string\print_string.cpp:82)
print_line(Variant v) Line 65 (godot4_fork\core\string\print_string.h:65)
RenderingDeviceVulkan::_free_internal(RID p_id) Line 8876 (godot4_fork\drivers\vulkan\rendering_device_vulkan.cpp:8876)
RenderingDeviceVulkan::free(RID p_id) Line 8883 (godot4_fork\drivers\vulkan\rendering_device_vulkan.cpp:8883)
RendererCanvasRenderRD::free_polygon(unsigned __int64 p_polygon) Line 339 (godot4_fork\servers\rendering\renderer_rd\renderer_canvas_render_rd.cpp:339)
RendererCanvasRender::Polygon::~Polygon() Line 154 (godot4_fork\servers\rendering\renderer_canvas_render.h:154)
RendererCanvasRender::Item::CommandPolygon::~CommandPolygon() (Unknown Source:0)
RendererCanvasRender::Item::CommandPolygon::`scalar deleting destructor'(unsigned int) (Unknown Source:0)
memdelete<RendererCanvasRender::Item::Command>(RendererCanvasRender::Item::Command * p_class) Line 112 (godot4_fork\core\os\memory.h:112)
RendererCanvasRender::Item::clear() Line 416 (godot4_fork\servers\rendering\renderer_canvas_render.h:416)
RendererCanvasRender::Item::~Item() Line 469 (godot4_fork\servers\rendering\renderer_canvas_render.h:469)
RendererCanvasCull::Item::~Item() (Unknown Source:0)
RendererCanvasCull::Item::`scalar deleting destructor'(unsigned int) (Unknown Source:0)
RID_Alloc<RendererCanvasCull::Item,1>::free(const RID & p_rid) Line 282 (godot4_fork\core\templates\rid_owner.h:282)
RID_Owner<RendererCanvasCull::Item,1>::free(const RID & p_rid) Line 460 (godot4_fork\core\templates\rid_owner.h:460)
RendererCanvasCull::free(RID p_rid) Line 2061 (godot4_fork\servers\rendering\renderer_canvas_cull.cpp:2061)
RenderingServerDefault::_free(RID p_rid) Line 54 (godot4_fork\servers\rendering\rendering_server_default.cpp:54)
RenderingServerDefault::free(RID p_rid) Line 955 (godot4_fork\servers\rendering\rendering_server_default.h:955)
CanvasItem::~CanvasItem() Line 1309 (godot4_fork\scene\main\canvas_item.cpp:1309)
Control::~Control() Line 3379 (godot4_fork\scene\gui\control.cpp:3379)
Container::~Container() (Unknown Source:0)
PanelContainer::~PanelContainer() (Unknown Source:0)
PanelContainer::`scalar deleting destructor'(unsigned int) (Unknown Source:0)
memdelete<Node>(Node * p_class) Line 112 (godot4_fork\core\os\memory.h:112)
Node::_notification(int p_notification) Line 170 (godot4_fork\scene\main\node.cpp:170)
Node::_notificationv(int p_notification, bool p_reversed) Line 45 (godot4_fork\scene\main\node.h:45)
CanvasItem::_notificationv(int p_notification, bool p_reversed) Line 45 (godot4_fork\scene\main\canvas_item.h:45)
Control::_notificationv(int p_notification, bool p_reversed) Line 47 (godot4_fork\scene\gui\control.h:47)
Container::_notificationv(int p_notification, bool p_reversed) Line 37 (godot4_fork\scene\gui\container.h:37)
SplitContainer::_notificationv(int p_notification, bool p_reversed) Line 54 (godot4_fork\scene\gui\split_container.h:54)
VSplitContainer::_notificationv(int p_notification, bool p_reversed) Line 132 (godot4_fork\scene\gui\split_container.h:132)
Object::notification(int p_notification, bool p_reversed) Line 792 (godot4_fork\core\object\object.cpp:792)
Object::_predelete() Line 197 (godot4_fork\core\object\object.cpp:197)
predelete_handler(Object * p_object) Line 1841 (godot4_fork\core\object\object.cpp:1841)
memdelete<Node>(Node * p_class) Line 105 (godot4_fork\core\os\memory.h:105)
Node::_notification(int p_notification) Line 170 (godot4_fork\scene\main\node.cpp:170)
Node::_notificationv(int p_notification, bool p_reversed) Line 45 (godot4_fork\scene\main\node.h:45)
CanvasItem::_notificationv(int p_notification, bool p_reversed) Line 45 (godot4_fork\scene\main\canvas_item.h:45)
Control::_notificationv(int p_notification, bool p_reversed) Line 47 (godot4_fork\scene\gui\control.h:47)
Container::_notificationv(int p_notification, bool p_reversed) Line 37 (godot4_fork\scene\gui\container.h:37)
BoxContainer::_notificationv(int p_notification, bool p_reversed) Line 37 (godot4_fork\scene\gui\box_container.h:37)
VBoxContainer::_notificationv(int p_notification, bool p_reversed) Line 92 (godot4_fork\scene\gui\box_container.h:92)
Object::notification(int p_notification, bool p_reversed) Line 792 (godot4_fork\core\object\object.cpp:792)
Object::_predelete() Line 197 (godot4_fork\core\object\object.cpp:197)
predelete_handler(Object * p_object) Line 1841 (godot4_fork\core\object\object.cpp:1841)
memdelete<Node>(Node * p_class) Line 105 (godot4_fork\core\os\memory.h:105)
Node::_notification(int p_notification) Line 170 (godot4_fork\scene\main\node.cpp:170)
Node::_notificationv(int p_notification, bool p_reversed) Line 45 (godot4_fork\scene\main\node.h:45)
CanvasItem::_notificationv(int p_notification, bool p_reversed) Line 45 (godot4_fork\scene\main\canvas_item.h:45)
Control::_notificationv(int p_notification, bool p_reversed) Line 47 (godot4_fork\scene\gui\control.h:47)
Container::_notificationv(int p_notification, bool p_reversed) Line 37 (godot4_fork\scene\gui\container.h:37)
SplitContainer::_notificationv(int p_notification, bool p_reversed) Line 54 (godot4_fork\scene\gui\split_container.h:54)
HSplitContainer::_notificationv(int p_notification, bool p_reversed) Line 124 (godot4_fork\scene\gui\split_container.h:124)
Object::notification(int p_notification, bool p_reversed) Line 792 (godot4_fork\core\object\object.cpp:792)
Object::_predelete() Line 197 (godot4_fork\core\object\object.cpp:197)
predelete_handler(Object * p_object) Line 1841 (godot4_fork\core\object\object.cpp:1841)
memdelete<Node>(Node * p_class) Line 105 (godot4_fork\core\os\memory.h:105)
Node::_notification(int p_notification) Line 170 (godot4_fork\scene\main\node.cpp:170)
Node::_notificationv(int p_notification, bool p_reversed) Line 45 (godot4_fork\scene\main\node.h:45)
CanvasItem::_notificationv(int p_notification, bool p_reversed) Line 45 (godot4_fork\scene\main\canvas_item.h:45)
Control::_notificationv(int p_notification, bool p_reversed) Line 47 (godot4_fork\scene\gui\control.h:47)
Container::_notificationv(int p_notification, bool p_reversed) Line 37 (godot4_fork\scene\gui\container.h:37)
SplitContainer::_notificationv(int p_notification, bool p_reversed) Line 54 (godot4_fork\scene\gui\split_container.h:54)
HSplitContainer::_notificationv(int p_notification, bool p_reversed) Line 124 (godot4_fork\scene\gui\split_container.h:124)
Object::notification(int p_notification, bool p_reversed) Line 792 (godot4_fork\core\object\object.cpp:792)
Object::_predelete() Line 197 (godot4_fork\core\object\object.cpp:197)
predelete_handler(Object * p_object) Line 1841 (godot4_fork\core\object\object.cpp:1841)
memdelete<Node>(Node * p_class) Line 105 (godot4_fork\core\os\memory.h:105)
Node::_notification(int p_notification) Line 170 (godot4_fork\scene\main\node.cpp:170)
Node::_notificationv(int p_notification, bool p_reversed) Line 45 (godot4_fork\scene\main\node.h:45)
CanvasItem::_notificationv(int p_notification, bool p_reversed) Line 45 (godot4_fork\scene\main\canvas_item.h:45)
Control::_notificationv(int p_notification, bool p_reversed) Line 47 (godot4_fork\scene\gui\control.h:47)
Container::_notificationv(int p_notification, bool p_reversed) Line 37 (godot4_fork\scene\gui\container.h:37)
SplitContainer::_notificationv(int p_notification, bool p_reversed) Line 54 (godot4_fork\scene\gui\split_container.h:54)
HSplitContainer::_notificationv(int p_notification, bool p_reversed) Line 124 (godot4_fork\scene\gui\split_container.h:124)
Object::notification(int p_notification, bool p_reversed) Line 792 (godot4_fork\core\object\object.cpp:792)
Object::_predelete() Line 197 (godot4_fork\core\object\object.cpp:197)
predelete_handler(Object * p_object) Line 1841 (godot4_fork\core\object\object.cpp:1841)
memdelete<Node>(Node * p_class) Line 105 (godot4_fork\core\os\memory.h:105)
Node::_notification(int p_notification) Line 170 (godot4_fork\scene\main\node.cpp:170)
Node::_notificationv(int p_notification, bool p_reversed) Line 45 (godot4_fork\scene\main\node.h:45)
CanvasItem::_notificationv(int p_notification, bool p_reversed) Line 45 (godot4_fork\scene\main\canvas_item.h:45)
Control::_notificationv(int p_notification, bool p_reversed) Line 47 (godot4_fork\scene\gui\control.h:47)
Container::_notificationv(int p_notification, bool p_reversed) Line 37 (godot4_fork\scene\gui\container.h:37)
BoxContainer::_notificationv(int p_notification, bool p_reversed) Line 37 (godot4_fork\scene\gui\box_container.h:37)
VBoxContainer::_notificationv(int p_notification, bool p_reversed) Line 92 (godot4_fork\scene\gui\box_container.h:92)
Object::notification(int p_notification, bool p_reversed) Line 792 (godot4_fork\core\object\object.cpp:792)
Object::_predelete() Line 197 (godot4_fork\core\object\object.cpp:197)
predelete_handler(Object * p_object) Line 1841 (godot4_fork\core\object\object.cpp:1841)
memdelete<Node>(Node * p_class) Line 105 (godot4_fork\core\os\memory.h:105)
Node::_notification(int p_notification) Line 170 (godot4_fork\scene\main\node.cpp:170)
Node::_notificationv(int p_notification, bool p_reversed) Line 45 (godot4_fork\scene\main\node.h:45)
CanvasItem::_notificationv(int p_notification, bool p_reversed) Line 45 (godot4_fork\scene\main\canvas_item.h:45)
Control::_notificationv(int p_notification, bool p_reversed) Line 47 (godot4_fork\scene\gui\control.h:47)
Panel::_notificationv(int p_notification, bool p_reversed) Line 37 (godot4_fork\scene\gui\panel.h:37)
Object::notification(int p_notification, bool p_reversed) Line 792 (godot4_fork\core\object\object.cpp:792)
Object::_predelete() Line 197 (godot4_fork\core\object\object.cpp:197)
predelete_handler(Object * p_object) Line 1841 (godot4_fork\core\object\object.cpp:1841)
memdelete<Node>(Node * p_class) Line 105 (godot4_fork\core\os\memory.h:105)
Node::_notification(int p_notification) Line 170 (godot4_fork\scene\main\node.cpp:170)
Node::_notificationv(int p_notification, bool p_reversed) Line 45 (godot4_fork\scene\main\node.h:45)
CanvasItem::_notificationv(int p_notification, bool p_reversed) Line 45 (godot4_fork\scene\main\canvas_item.h:45)
Control::_notificationv(int p_notification, bool p_reversed) Line 47 (godot4_fork\scene\gui\control.h:47)
Object::notification(int p_notification, bool p_reversed) Line 792 (godot4_fork\core\object\object.cpp:792)
Object::_predelete() Line 197 (godot4_fork\core\object\object.cpp:197)
predelete_handler(Object * p_object) Line 1841 (godot4_fork\core\object\object.cpp:1841)
memdelete<Node>(Node * p_class) Line 105 (godot4_fork\core\os\memory.h:105)
Node::_notification(int p_notification) Line 170 (godot4_fork\scene\main\node.cpp:170)
Node::_notificationv(int p_notification, bool p_reversed) Line 45 (godot4_fork\scene\main\node.h:45)
EditorNode::_notificationv(int p_notification, bool p_reversed) Line 112 (godot4_fork\editor\editor_node.h:112)
Object::notification(int p_notification, bool p_reversed) Line 792 (godot4_fork\core\object\object.cpp:792)
Object::_predelete() Line 197 (godot4_fork\core\object\object.cpp:197)
predelete_handler(Object * p_object) Line 1841 (godot4_fork\core\object\object.cpp:1841)
memdelete<Node>(Node * p_class) Line 105 (godot4_fork\core\os\memory.h:105)
Node::_notification(int p_notification) Line 170 (godot4_fork\scene\main\node.cpp:170)
Node::_notificationv(int p_notification, bool p_reversed) Line 45 (godot4_fork\scene\main\node.h:45)
Viewport::_notificationv(int p_notification, bool p_reversed) Line 89 (godot4_fork\scene\main\viewport.h:89)
Window::_notificationv(int p_notification, bool p_reversed) Line 44 (godot4_fork\scene\main\window.h:44)
Object::notification(int p_notification, bool p_reversed) Line 792 (godot4_fork\core\object\object.cpp:792)
Object::_predelete() Line 197 (godot4_fork\core\object\object.cpp:197)
predelete_handler(Object * p_object) Line 1841 (godot4_fork\core\object\object.cpp:1841)
memdelete<Window>(Window * p_class) Line 105 (godot4_fork\core\os\memory.h:105)
SceneTree::finalize() Line 585 (godot4_fork\scene\main\scene_tree.cpp:585)
OS_Windows::run() Line 1017 (godot4_fork\platform\windows\os_windows.cpp:1017)
widechar_main(int argc, wchar_t * * argv) Line 181 (godot4_fork\platform\windows\godot_windows.cpp:181)
_main() Line 203 (godot4_fork\platform\windows\godot_windows.cpp:203)
main(int argc, char * * argv) Line 217 (godot4_fork\platform\windows\godot_windows.cpp:217)
WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * lpCmdLine, int nCmdShow) Line 231 (godot4_fork\platform\windows\godot_windows.cpp:231)
invoke_main() Line 107 (d:\a01\_work\12\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:107)
__scrt_common_main_seh() Line 288 (d:\a01\_work\12\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288)
__scrt_common_main() Line 331 (d:\a01\_work\12\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:331)
WinMainCRTStartup(void * __formal) Line 17 (d:\a01\_work\12\s\src\vctools\crt\vcstartup\src\startup\exe_winmain.cpp:17)
kernel32.dll!00007fffb64874b4() (Unknown Source:0)
ntdll.dll!00007fffb66626a1() (Unknown Source:0)
```

It seems the print handler of the editor is unregistered too late. If that's the case, it causes the print handler to attempt accessing the editor's log when that UI has been (or is being) destroyed.

This makes it difficult to debug some things, or could be problematic for errors to be reported properly in the system console when they occur in this spot.


### Steps to reproduce

Add `print_line(String("Freed {0}").format(varray(p_id)));` at the end of `RenderingDeviceVulkan::_free_internal`, run the editor in debug mode with a debugger attached (I use the debug CRT), and close the editor. I don't know if it will actually reproduce immediately, but it did for me as I was debugging something else in a project that allocated a lot of things.


### Minimal reproduction project

N.A