godotengine / godot

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

Moving RichTextLabel into a CenterContainer node causes editor to crash #78912

Closed aldocd4 closed 1 year ago

aldocd4 commented 1 year ago

Godot version

v4.1.rc2.mono.official [46424488e]

System information

Windows 11 - v4.1.rc2 - Vulkan

Issue description

I tried to move a RichTextLabel into a CenterContainer node and the editor crashed.

It seems the latest working version was v4.1.beta2.mono.official [a2575cba4] I have a crash with all the snapshots that came after that one.

ERROR: Failed method: CanvasItem::_redraw_callback. Message queue out of memory. Message queue out of memory. Try increasing 'memory. at: push_callablep (core/object/message_queue.cpp:96) ERROR: Failed method: CanvasItem::_redraw_callback. Message queue out of memory. Message queue out of memory. Try increasing 'memory. at: push_callablep (core/object/message_queue.cpp:96) ERROR: Failed method: CanvasItem::_redraw_callback. Message queue out of memory. Message queue out of memory. Try increasing 'memory. at: push_callablep (core/object/message_queue.cpp:96) ERROR: Failed method: CanvasItem::_redraw_callback. Message queue out of memory. Message queue out of memory. Try increasing 'memory. at: push_callablep (core/object/message_queue.cpp:96) ERROR: Failed method: EditorToaster::_error_handler_impl. Message queue out of memory. Message queue out of memory. Try increasing '. at: push_callablep (core/object/message_queue.cpp:96) ERROR: Failed method: EditorToaster::_error_handler_impl. Message queue out of memory. Message queue out of memory. Try increasing '.

Steps to reproduce

Minimal reproduction project

bug-ui.zip

capnm commented 1 year ago

image

(./core/object/message_queue.cpp:96) push_callablep: Failed method: Control::_update_minimum_size. Message queue out of memory. Message queue out of memory. Try increasing 'memory/limits/message_queue/max_size_mb' in project settings.

backtrace leading to the failure:
* thread #1, name = 'godot.linuxbsd.', stop reason = signal SIGSEGV: invalid address (fault address: 0x722d00576e)
  * frame #0: 0x000055555ca15185 godot.linuxbsd.editor.dev.x86_64.llvm`Callable::get_object(this=0x000055555f5d9320) const at callable.cpp:136:41
    frame #1: 0x000055555ccb83e1 godot.linuxbsd.editor.dev.x86_64.llvm`CallQueue::statistics(this=0x000055555dc6f9b0) at message_queue.cpp:422:39
    frame #2: 0x000055555ccb70d9 godot.linuxbsd.editor.dev.x86_64.llvm`CallQueue::push_callablep(this=0x000055555dc6f9b0, p_callable=<unavailable>, p_args=0x0000000000000000, p_argcount=0, p_show_error=false) at message_queue.cpp:97:4
    frame #3: 0x000055555b02af4b godot.linuxbsd.editor.dev.x86_64.llvm`Control::update_minimum_size() [inlined] Error CallQueue::push_callable<>(this=0x000055555dc6f9b0, p_callable=0x00007fffffffd5e0) at message_queue.h:130:10
    frame #4: 0x000055555b02af29 godot.linuxbsd.editor.dev.x86_64.llvm`Control::update_minimum_size(this=<unavailable>) at control.cpp:1628:33
    frame #5: 0x000055555b096379 godot.linuxbsd.editor.dev.x86_64.llvm`Container::_child_minsize_changed(this=<unavailable>) at container.cpp:37:2
    frame #6: 0x000055555ccc0a48 godot.linuxbsd.editor.dev.x86_64.llvm`Object::emit_signalp(this=0x0000555574ac6750, p_name=0x000055555edb7228, p_args=0x0000000000000000, p_argcount=0) at object.cpp:1068:15
    frame #7: 0x000055555b0a47d2 godot.linuxbsd.editor.dev.x86_64.llvm`Control::_update_minimum_size() [inlined] Error Object::emit_signal<>(this=0x0000555574ac6750, p_name=<unavailable>) at object.h:881:10
    frame #8: 0x000055555b0a47b3 godot.linuxbsd.editor.dev.x86_64.llvm`Control::_update_minimum_size(this=0x0000555574ac6750) at control.cpp:1592:3
    frame #9: 0x000055555ccb9817 godot.linuxbsd.editor.dev.x86_64.llvm`CallQueue::_call_function(this=<unavailable>, p_callable=0x0000555577a6f098, p_args=0x0000555577a6f0b0, p_argcount=0, p_show_error=false) at message_queue.cpp:219:13
    frame #10: 0x000055555ccb9c9b godot.linuxbsd.editor.dev.x86_64.llvm`CallQueue::flush(this=0x000055555dc6f9b0) at message_queue.cpp:320:6
    frame #11: 0x000055555af36ab5 godot.linuxbsd.editor.dev.x86_64.llvm`SceneTree::physics_process(this=0x000055555f67f8d0, p_time=0) at scene_tree.cpp:471:33
    frame #12: 0x0000555558fa153e godot.linuxbsd.editor.dev.x86_64.llvm`Main::iteration() at main.cpp:3383:45
frame #8: 0x000055555b0a47b3 godot.linuxbsd.editor.dev.x86_64.llvm`Control::_update_minimum_size(this=0x0000555573af5bd0) at control.cpp:1592:3
   1589     if (minsize != data.last_minimum_size) {
   1590         data.last_minimum_size = minsize;
   1591         _size_changed();
-> 1592         emit_signal(SceneStringNames::get_singleton()->minimum_size_changed);
   1593     }
   1594 }
akien-mga commented 1 year ago

The crash happens before MessageQueue runs out of memory, as usual.

The infinite loop's stacktrace seems to be:

0x0000000006cb4299 in TextServerAdvanced::_shaped_text_substr (this=0xbeaf7d0, p_shaped=..., p_start=0, p_length=8) at modules/text_server_adv/text_server_adv.cpp:4258
4258                    new_sd->extra_spacing[i] = sd->extra_spacing[i];
(gdb) bt
#0  0x0000000006cb4299 in TextServerAdvanced::_shaped_text_substr (this=0xbeaf7d0, p_shaped=..., p_start=0, p_length=8) at modules/text_server_adv/text_server_adv.cpp:4258
#1  0x0000000006cc9a36 in TextServerAdvanced::shaped_text_substr (this=0xbeaf7d0, arg1=..., arg2=0, arg3=8) at modules/text_server_adv/text_server_adv.h:888
#2  0x0000000008fd0591 in TextParagraph::_shape_lines (this=0x23b73f10) at ./scene/resources/text_paragraph.cpp:194
#3  0x0000000008fd2eb3 in TextParagraph::get_size (this=0x23b73f10) at ./scene/resources/text_paragraph.cpp:534
#4  0x00000000086fda23 in RichTextLabel::Line::get_height (this=0x1f9fd230, line_separation=0) at ./scene/gui/rich_text_label.h:119
#5  0x00000000086fec2a in RichTextLabel::_calculate_line_vertical_offset (this=0x22d5b580, line=...) at ./scene/gui/rich_text_label.cpp:1724
#6  0x00000000085ef920 in RichTextLabel::_resize_line (this=0x22d5b580, p_frame=0x1f988c50, p_line=0, p_base_font=..., p_base_font_size=16, p_width=-7, p_h=0) at ./scene/gui/rich_text_label.cpp:448
#7  0x000000000860220e in RichTextLabel::_validate_line_caches (this=0x22d5b580) at ./scene/gui/rich_text_label.cpp:2854
#8  0x00000000085fd477 in RichTextLabel::_notification (this=0x22d5b580, p_what=30) at ./scene/gui/rich_text_label.cpp:1832
#9  0x00000000086fd916 in RichTextLabel::_notificationv (this=0x22d5b580, p_notification=30, p_reversed=false) at ./scene/gui/rich_text_label.h:41
#10 0x000000000a5e0423 in Object::notification (this=0x22d5b580, p_notification=30, p_reversed=false) at ./core/object/object.cpp:796
#11 0x0000000008335add in CanvasItem::_redraw_callback (this=0x22d5b580) at ./scene/main/canvas_item.cpp:140
#12 0x0000000007477bba in call_with_variant_args_helper<CanvasItem>(CanvasItem*, void (CanvasItem::*)(), Variant const**, Callable::CallError&, IndexSequence<>) (p_instance=0x22d5b580, 
    p_method=(void (CanvasItem::*)(CanvasItem * const)) 0x8335a46 <CanvasItem::_redraw_callback()>, p_args=0x0, r_error=...) at ./core/variant/binder_common.h:303
#13 0x0000000007468d65 in call_with_variant_args<CanvasItem> (p_instance=0x22d5b580, p_method=(void (CanvasItem::*)(CanvasItem * const)) 0x8335a46 <CanvasItem::_redraw_callback()>, p_args=0x0, p_argcount=0, r_error=...)
    at ./core/variant/binder_common.h:417
#14 0x000000000742b894 in CallableCustomMethodPointer<CanvasItem>::call (this=0x22d51860, p_arguments=0x0, p_argcount=0, r_return_value=..., r_call_error=...) at ./core/object/callable_method_pointer.h:104
#15 0x000000000a2c5da9 in Callable::callp (this=0x24a211e8, p_arguments=0x0, p_argcount=0, r_return_value=..., r_call_error=...) at ./core/variant/callable.cpp:50
#16 0x000000000a5d95ff in CallQueue::_call_function (this=0xbbb16b0, p_callable=..., p_args=0x24a21200, p_argcount=0, p_show_error=false) at ./core/object/message_queue.cpp:219
#17 0x000000000a5d9dac in CallQueue::flush (this=0xbbb16b0) at ./core/object/message_queue.cpp:320
#18 0x0000000008383b11 in SceneTree::physics_process (this=0xda088b0, p_time=0.016666666666666666) at ./scene/main/scene_tree.cpp:471
#19 0x00000000057194cd in Main::iteration () at main/main.cpp:3383
#20 0x000000000569385a in OS_LinuxBSD::run (this=0x7fff0784cc30) at platform/linuxbsd/os_linuxbsd.cpp:912
#21 0x000000000568ab00 in main (argc=2, argv=0x7fff0784d218) at platform/linuxbsd/godot_linuxbsd.cpp:74
Sauermann commented 1 year ago

I was able to bisect it to #78241

bruvzg commented 1 year ago

Seems like it's caused by vscroll->get_combined_minimum_size() call.

capnm commented 1 year ago

Visually CenterContainer squeezes (fit content) to zero size and when you put label inside it produces vertical artefacts...

image

Looks like it loops in emitting signals to resize RichTextLabel width to almost zero. (At least it stops and the editor doesn't crash if you disable scroll_active)

image

bruvzg commented 1 year ago

Seems like it's caused by vscroll->get_combined_minimum_size() call.

Not, this was wrong. It's something wrong with the sizing. Infinite loop is container sort childrenresize rtlrtl update_min_sizecontainer sort children.

bruvzg commented 1 year ago

I guess the issue is update_min_size is called when processing is done, instead it should be called when control properties are changed and shaped data is invalidated. The same is true for Label, which had the same issue (not use why it's not crashing as well).

akien-mga commented 1 year ago

See also #78932 and #78849 (potential duplicates).