godotengine / godot

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

Infinite loop in rich_text_label.cpp (ERROR: _process_line: Index line = 0 is out of bounds) #38058

Open DrMoriarty opened 4 years ago

DrMoriarty commented 4 years ago

Bugsquad note: This issue has been confirmed several times already. No need to confirm it further.


Godot version: Godot 3.2.2.beta1

OS/device including version: MacOSX 10.14.6 (18G95)

Issue description: Today all day I'm working on fixing pvrtc and twice my godot did hung up with this errors:

   At: scene/gui/rich_text_label.cpp:170.
ERROR: _process_line: Index line = 0 is out of bounds (l.offset_caches.size() = 0).
   At: scene/gui/rich_text_label.cpp:170.
ERROR: _process_line: Index line = 0 is out of bounds (l.offset_caches.size() = 0).
   At: scene/gui/rich_text_label.cpp:170.
ERROR: _process_line: Index line = 0 is out of bounds (l.offset_caches.size() = 0).
   At: scene/gui/rich_text_label.cpp:170.
ERROR: _process_line: Index line = 0 is out of bounds (l.offset_caches.size() = 0).

It repeats in infinite cycle and godot interface is frozen. I can not reproduce it when I want to. But two times it happened.

Steps to reproduce:

Minimal reproduction project:

aaronfranke commented 4 years ago

This code is weird. line is guaranteed to be 0 here, so the check whether line is between 0 and the size should be simplified to just a check for if the size is 0. I don't know why it would be 0, though.

Eoin-ONeill-Yokai commented 4 years ago

I haven't looked majorly into this, but I think that the caching system and this check might be what's returning garbage line size values as well. So I think this is possibly related to #18722. @DrMoriarty I haven't had a chance to reproduce this myself and can't find a way to reproduce it. If someone else can try getting a gdb trace on this, that'd be very useful.

For the record, as someone who has worked on this class within the last year (or two I suppose), the problem this class currently has is that the codeflow is hard to parse because of a combination of extensive macro-use and arguably too many vaguely named variables. It's kind of on my todo to go back to this class and clean it up to make it easier to work with, but I never really find the time.

line is guaranteed to be 0 here, so the check whether line is between 0 and the size should be simplified to just a check for if the size is 0.

@aaronfranke Indeed. I think there's a very high likelihood that these checks were actually intended for the macro define on line 216 and were but in the wrong place probably because the macro text is greyed out.

HungryProton commented 4 years ago

Not sure if it's related but this issue consistently happens since I tried adding multi-threading to my addon. I'll see if I can produce a minimal reproduction project but the code is so convoluted I'm having a hard time tracking down this issue.

BattyBovine commented 4 years ago

Just wanted to confirm that I'm now getting this same error, every single time I push a build to my Android phone for debugging, and it seems to have started as soon as I started using ResourceInteractiveLoader to switch scenes. Removing that part of the code doesn't seem to have stopped this issue from happening every time I run the debugger, but disabling "Small Deploy with Network FS" seems to work. This also seems to only affect Android as far as I can tell, and not when I run a debug build on Windows 10.

lupoDharkael commented 4 years ago

I'm working on a C++ module and I'm having the same experience as @HungryProton. I do procedural generation from a thread and this happens sometimes when I use print_line(). The reproduction rate seems arbitrary.

lupoDharkael commented 4 years ago

@Eoin-ONeill-Yokai I have a trace from commit 561438c5f67fcd2b4a3132d36b32333e4d8eb6c5

GDB bt
#0  0x00007ffff76ef4bf in write () from /lib64/libc.so.6
#1  0x00007ffff767f4cd in _IO_file_write@@GLIBC_2.2.5 () from /lib64/libc.so.6
#2  0x00007ffff767e826 in new_do_write () from /lib64/libc.so.6
#3  0x00007ffff767fbfe in __GI__IO_file_xsputn () from /lib64/libc.so.6
#4  0x00007ffff766b6b1 in buffered_vfprintf () from /lib64/libc.so.6
#5  0x00007ffff7668654 in __vfprintf_internal () from /lib64/libc.so.6
#6  0x0000000006e549cd in StdLogger::logv (this=0x77d6750, p_format=0x1b21d10 "%sERROR:%s %s\n", 
    p_list=0x7fffffffab70, p_err=true) at core/io/logger.cpp:230
#7  0x0000000006e53901 in Logger::logf_error (this=0x77d6750, p_format=0x1b21d10 "%sERROR:%s %s\n")
    at core/io/logger.cpp:100
#8  0x00000000048b0543 in UnixTerminalLogger::log_error (this=0x77d6750, 
    p_function=0x1b453da "_process_line", p_file=0x1b453e8 "scene/gui/rich_text_label.cpp", p_line=176, 
    p_code=0x3a4cb630 "Index line = 0 is out of bounds (l.offset_caches.size() = 0).", 
    p_rationale=0x1b8389b "", p_type=Logger::ERR_ERROR) at drivers/unix/os_unix.cpp:582
#9  0x0000000006e54c59 in CompositeLogger::log_error (this=0x77d6790, 
    p_function=0x1b453da "_process_line", p_file=0x1b453e8 "scene/gui/rich_text_label.cpp", p_line=176, 
    p_code=0x3a4cb630 "Index line = 0 is out of bounds (l.offset_caches.size() = 0).", 
    p_rationale=0x1b8389b "", p_type=Logger::ERR_ERROR) at core/io/logger.cpp:264
#10 0x0000000006cac54a in OS::print_error (this=0x7fffffffd5e8, p_function=0x1b453da "_process_line", 
    p_file=0x1b453e8 "scene/gui/rich_text_label.cpp", p_line=176, 
    p_code=0x3a4cb630 "Index line = 0 is out of bounds (l.offset_caches.size() = 0).", 
    p_rationale=0x1b8389b "", p_type=Logger::ERR_ERROR) at core/os/os.cpp:120
#11 0x0000000006ab6e57 in _err_print_error (p_function=0x1b453da "_process_line", 
    p_file=0x1b453e8 "scene/gui/rich_text_label.cpp", p_line=176, 
    p_error=0x3a4cb630 "Index line = 0 is out of bounds (l.offset_caches.size() = 0).", 
    p_message=0x1b8389b "", p_type=ERR_HANDLER_ERROR) at core/error_macros.cpp:81
#12 0x0000000006ab7513 in _err_print_index_error (p_function=0x1b453da "_process_line", 
    p_file=0x1b453e8 "scene/gui/rich_text_label.cpp", p_line=176, p_index=0, p_size=0, 
    p_index_str=0x1a8d3f2 "line", p_size_str=0x1a18d15 "l.offset_caches.size()", p_message=0x1b8389b "", 
    fatal=false) at core/error_macros.cpp:110
#13 0x0000000005977a06 in RichTextLabel::_process_line (this=0xe7d23d0, p_frame=0xe7d2a90, p_ofs=..., 
    y=@0x7fffffffc91c: 172, p_width=1333, p_line=470075, p_mode=RichTextLabel::PROCESS_DRAW, 
    p_base_font=..., p_base_color=..., p_font_color_shadow=..., p_shadow_as_outline=false, 
    shadow_ofs=..., p_click_pos=..., r_click_item=0x0, r_click_char=0x0, r_outside=0x0, 
    p_char_count=18487) at scene/gui/rich_text_label.cpp:176
#14 0x00000000059818fe in RichTextLabel::_notification (this=0xe7d23d0, p_what=30)
    at scene/gui/rich_text_label.cpp:1039
#15 0x000000000599626b in RichTextLabel::_notificationv (this=0xe7d23d0, p_notification=30, 
    p_reversed=false) at scene/gui/rich_text_label.h:39
#16 0x0000000006b45a4b in Object::notification (this=0xe7d23d0, p_notification=30, p_reversed=false)
    at core/object.cpp:914
#17 0x00000000056d24d8 in CanvasItem::_update_callback (this=0xe7d23d0) at scene/main/canvas_item.cpp:452
#18 0x00000000056e7764 in MethodBind0::call (this=0x8acf450, p_object=0xe7d23d0, p_args=0x0, 
    p_arg_count=0, r_error=...) at ./core/method_bind.gen.inc:147
#19 0x0000000006b48f6a in Object::call (this=0xe7d23d0, p_method=..., p_args=0x0, p_argcount=0, 
    r_error=...) at core/object.cpp:904
#20 0x0000000006a86323 in Callable::call (this=0x7fffe9e31020, p_arguments=0x0, p_argcount=0, 
    r_return_value=..., r_call_error=...) at core/callable.cpp:52
#21 0x0000000006b3d043 in MessageQueue::_call_function (this=0x78d1990, p_callable=..., 
    p_args=0x7fffe9e31038, p_argcount=0, p_show_error=false) at core/message_queue.cpp:253
#22 0x0000000006b3d392 in MessageQueue::flush (this=0x78d1990) at core/message_queue.cpp:303
#23 0x000000000575cba5 in SceneTree::idle (this=0x911c180, p_time=0.020833334)
    at scene/main/scene_tree.cpp:460
#24 0x00000000035535b5 in Main::iteration () at main/main.cpp:2190
#25 0x00000000035168e6 in OS_LinuxBSD::run (this=0x7fffffffd5e8) at platform/linuxbsd/os_linuxbsd.cpp:259
#26 0x0000000003514276 in main (argc=4, argv=0x7fffffffdac8) at platform/linuxbsd/godot_linuxbsd.cpp:56
ebeem commented 4 years ago

I am using threads, and it's causing this issue to me.

I don't understand why it works sometimes, shouldn't we always update GUI from the main thread? as a workaround, instead of updating the control immediately (richtext to store console/terminal logs in my case), I am storing the list of strings I want to add to my log.

I am actually wondering how it works sometimes anyway, I don't think we can update the GUI from a thread other than the main, it seems like there's something that handles such situations in Godot?

before

        private Node _console;
        private Node Console
        {
            get
            {
                if (_console == null)
                    _console = GetNode("/root/Console");
                return _console;
            }
        }
        public void WriteLine(string text)
        {
            Console.Call("writeLine", text);
        }

        public void Write(string text)
        {
            Console.Call("write", text);
        }

after

        private Node _console;
        private Queue<string> _logLines = new Queue<string>();
        private Queue<string> _logs = new Queue<string>();

        private Node Console
        {
            get
            {
                if (_console == null)
                    _console = GetNode("/root/Console");
                return _console;
            }
        }

        public void WriteLine(string text)
        {
            _logLines.Enqueue(text);
        }

        public void Write(string text)
        {
            _logs.Enqueue(text);
        }

        public override void _Process(float delta)
        {
            base._Process(delta);
            while(_logs.Count > 0)
                Console.Call("write", _logs.Dequeue());
            while(_logLines.Count > 0)
                Console.Call("writeLine", _logLines.Dequeue());
        }
Rubonnek commented 4 years ago

This just started happening to me quite often in 3.2 branch at commit 49b3750b3671e6c0c3edd0ca4d41df85593ff26f.

I'm not explicitly using threads in GDScript land -- only the intrinsic threads the engine itself uses, and the threaded LSP server.

Here's the backtrace I was able to catch:

#0  RichTextLabel::_process_line (this=0xe6a7810, p_frame=0xe6a7f90, p_ofs=..., y=@0x7fffffffcec4: 0, p_width=-8, p_line=0, p_mode=RichTextLabel::PROCESS_DRAW, p_base_font=..., p_base_color=..., p_font_color_shadow=..., p_shadow_as_outline=false, shadow_ofs=..., p_click_pos=..., r_click_item=0x0, r_click_char=0x0, r_outside=0x0, p_char_count=0) at scene/gui/rich_text_label.cpp:170
#1  0x000000000320a8c4 in RichTextLabel::_notification (this=0xe6a7810, p_what=30) at scene/gui/rich_text_label.cpp:1025
#2  0x0000000003230d1d in RichTextLabel::_notificationv (this=0xe6a7810, p_notification=30, p_reversed=false) at scene/gui/rich_text_label.h:39
#3  0x000000000512b898 in Object::notification (this=0xe6a7810, p_notification=30, p_reversed=false) at core/object.cpp:932
#4  0x00000000037e4a5e in CanvasItem::_update_callback (this=0xe6a7810) at scene/2d/canvas_item.cpp:459
#5  0x000000000058820a in MethodBind0::call (this=0xb370ed0, p_object=0xe6a7810, p_args=0x0, p_arg_count=0, r_error=...) at ./core/method_bind.gen.inc:59
#6  0x000000000512b62f in Object::call (this=0xe6a7810, p_method=..., p_args=0x0, p_argcount=0, r_error=...) at core/object.cpp:922
#7  0x0000000005114680 in MessageQueue::_call_function (this=0x9edfb40, p_target=0xe6a7810, p_func=..., p_args=0x7ffff692b5f0, p_argcount=0, p_show_error=false) at core/message_queue.cpp:250
#8  0x0000000005114aa7 in MessageQueue::flush (this=0x9edfb40) at core/message_queue.cpp:297
#9  0x0000000002f0f555 in SceneTree::iteration (this=0xb840020, p_time=0.0166666675) at scene/main/scene_tree.cpp:483
#10 0x00000000004ae8e8 in Main::iteration () at main/main.cpp:2084
#11 0x0000000000453b75 in OS_X11::run (this=0x7fffffffd7f0) at platform/x11/os_x11.cpp:3233
#12 0x00000000004387c7 in main (argc=2, argv=0x7fffffffe008) at platform/x11/godot_x11.cpp:56
Eoin-ONeill-Yokai commented 4 years ago

@Rubonnek Well, since there's currently a planned refactor (as seen in RichTextLabel issues tracker), I think that this would likely be addressed by that refactor.

Out of curiosity, do you happen to have a scene configuration where this is quickly reproducible?

Rubonnek commented 4 years ago

@Eoin-ONeill-Yokai Unfortunately I wasn't able to reproduce the issue consistently. It just happened to me five times in a row in the same project, but suddenly it stopped happening. I spent a couple of hours trying to reproduce it but to no avail.

Rubonnek commented 4 years ago

I can add that it always happened when one of my i3-wm windows was full screen, the project was running with a RichTextLabel node in it, and all three windows (i.e. the Editor, the running project, and my external text editor) were in the same workspace. My external editor connected to the LSP server covered the Editor as well as the project I was running, as I was debugging the code.

RevoluPowered commented 4 years ago

I'm not using threads, for me if you enable verbose debugging and output a bunch into the godot console on re-importing an FBX file which is particularly big and click the scrollbar it will sometimes trigger the problem, but only if the log is super long.

maybe someone could make a print_verbose somewhere with like 100,000 lines into the console to debug the issue it might reveal the problem

akien-mga commented 3 years ago

Related (likely duplicate, but both have useful debugging info) to #17815. See also #43705 which is about this issue happening when printing from threads.

leetNightshade commented 3 years ago

I was on 3.3.3-RC and just switched to 3.3.3-Stable, and am now seeing this issue.

JoanPotatoes2021 commented 3 years ago

I was on v3.3.3.stable.official [b973f997f], running with -verbose on the editor and testing the game. I was messing with a script, and decided to run a test scene, after I pressed run scene, I noticed that the debug print panel it was still loading some texture resources from my project, the game started on the scene running, everything okay, then suddenly it frooze, upon going to the print there was the error:

ERROR: _process_line: Index line = 0 is out of bounds (l.offset_caches.size() = 0).
   At: scene/gui/rich_text_label.cpp:170

Looped to infinity until I closed Godot. I had this bug twice in a row, I was going to update to a newer version to test if it still happenned, but it suddenly stopped giving the error. I don't know what triggered, and the thing is, I never had that bug, and I did not executed any major changes aside from running with -verbose, and I also didn't edited anything related to richtextlabels in a loong while, so I cannot pinpoint the error. Also found 2 closed issues with the same problem.

https://github.com/godotengine/godot/issues/29491 https://github.com/godotengine/godot/issues/16072

DataPlusProgram commented 3 years ago

I've ran into this using 3.4 stable. Where the editor will indefinitely freeze up while continuously outputting: Index line = 0 is out of bounds (l.offset_caches.size() = 0).

It happens with my plugin when threading and printing is involved.

Removing the print statements stopped the editor from outputting this error and freezing.

resinten commented 2 years ago

I'm currently on 3.4-stable. I've had the editor periodically crash when I switch back to it after making changes in VSCode. It freezes for about 30 seconds then finally crashes. It's rare, so I don't have any idea how to reproduce it. It's been happening for several weeks. It wasn't until today that I ran the editor from the command line and saw this error message. I couldn't see whether there was anything before it in the logs because it prints it out a LOT. Weirdly, I'm not using RichTextLabel anywhere in the code, so I take it this is related to an editor UI widget thing rather than something in the scene. Also, most recently, this happened when I made changes to scripts that are not used at all in the scene that I have open, so not sure what would've caused it.

image
Shfty commented 2 years ago

I'm seeing this on 3.3.4 stable with scripts that run in tool mode - if I spawn a thread to parse an OBJ file and call print() from the parsing code, the editor will lock up and proceed to fill my system's RAM with error spam until killed. Evidently the offending RichTextLabel is the debug console itself in this case.

Removing the print statements prevents the issue, but also makes debugging that code next to impossible without creating a non-threaded sandbox in which to test it.

Eoin-ONeill-Yokai commented 2 years ago

I'm seeing this on 3.3.4 stable with scripts that run in tool mode - if I spawn a thread to parse an OBJ file and call print() from the parsing code, the editor will lock up and proceed to fill my system's RAM with error spam until killed. Evidently the offending RichTextLabel is the debug console itself in this case.

Removing the print statements prevents the issue, but also makes debugging that code next to impossible without creating a non-threaded sandbox in which to test it.

If this is reproducible with a stack trace, could you supply a minimum testing environment? It might help with debugging.

petterthowsen commented 2 years ago

Not sure if it's related but this issue consistently happens since I tried adding multi-threading to my addon. I'll see if I can produce a minimal reproduction project but the code is so convoluted I'm having a hard time tracking down this issue.

Same here. Doing a terrain sculpting addon. I thought it went away, but it's back now :'(

I've ran into this using 3.4 stable. Where the editor will indefinitely freeze up while continuously outputting: Index line = 0 is out of bounds (l.offset_caches.size() = 0).

It happens with my plugin when threading and printing is involved.

Removing the print statements stopped the editor from outputting this error and freezing.

Seems to be the same here!

tomeyro commented 2 years ago

Same happening to me. Using v3.4.3 to build an addon with multi-threads and this was popping up a lot.

I did something horrible just to be able to use print to debug:

func fakeprint(msg):
    print(msg)

Then inside a method that runs on a different thread I do:

func whatever():
    call_deferred("fakeprint", ["print me"])
DataPlusProgram commented 2 years ago

I am still getting this in 3.5.rc and might be able to provide additional information.

This error will not occur if the output console is minimized so that it's no longer visible.

I have also been able to get the following stack log that leads to Index line = 0 is out of bounds (l.offset_caches.size() = 0). being printed

godot.windows.opt.tools.64.exe!write_text_ansi_nolock(const int fh, const char * const buffer, const unsigned int buffer_size) Line 415 C++
godot.windows.opt.tools.64.exe!_write_nolock(int fh, const void * buffer, unsigned int buffer_size) Line 679    C++
godot.windows.opt.tools.64.exe!_write(int fh, const void * buffer, unsigned int size) Line 64   C++
godot.windows.opt.tools.64.exe!write_buffer_nolock<char>(const char c, const __crt_stdio_stream stream) Line 95 C++
[Inline Frame] godot.windows.opt.tools.64.exe!common_flush_and_write_nolock(const int) Line 174 C++
godot.windows.opt.tools.64.exe!__acrt_stdio_flush_and_write_narrow_nolock(int c, _iobuf * stream) Line 190  C++
godot.windows.opt.tools.64.exe!_fputwc_nolock(wchar_t c, _iobuf * public_stream) Line 64    C++
[Inline Frame] godot.windows.opt.tools.64.exe!__crt_char_traits<wchar_t>::puttc_nolock(const wchar_t &) Line 124    C++
[Inline Frame] godot.windows.opt.tools.64.exe!__crt_stdio_output::stream_output_adapter<wchar_t>::write_character_without_count_update(const wchar_t c) Line 166    C++
godot.windows.opt.tools.64.exe!__crt_stdio_output::output_adapter_common<wchar_t,__crt_stdio_output::stream_output_adapter<wchar_t>>::write_string_impl(const wchar_t * const string, const int length, int * const count_written, __crt_deferred_errno_cache & status) Line 86 C++
[Inline Frame] godot.windows.opt.tools.64.exe!__crt_stdio_output::stream_output_adapter<wchar_t>::write_string(const wchar_t * const string, const int length, int * const count_written, __crt_deferred_errno_cache &) Line 182    C++
godot.windows.opt.tools.64.exe!__crt_stdio_output::output_processor<wchar_t,__crt_stdio_output::stream_output_adapter<wchar_t>,__crt_stdio_output::standard_base<wchar_t,__crt_stdio_output::stream_output_adapter<wchar_t>>>::write_stored_string_tchar(wchar_t __formal) Line 2735    C++
godot.windows.opt.tools.64.exe!__crt_stdio_output::output_processor<wchar_t,__crt_stdio_output::stream_output_adapter<wchar_t>,__crt_stdio_output::standard_base<wchar_t,__crt_stdio_output::stream_output_adapter<wchar_t>>>::state_case_type() Line 2150  C++
godot.windows.opt.tools.64.exe!__crt_stdio_output::output_processor<wchar_t,__crt_stdio_output::stream_output_adapter<wchar_t>,__crt_stdio_output::standard_base<wchar_t,__crt_stdio_output::stream_output_adapter<wchar_t>>>::process() Line 1699  C++
godot.windows.opt.tools.64.exe!common_vfprintf::__l2::<lambda>() Line 49    C++
godot.windows.opt.tools.64.exe!__crt_seh_guarded_call<int>::operator()<<lambda_676bd5779251ec186b530f0a904b4b35>,int <lambda>(void) &,<lambda_10027885da78ada7fb00668d7e2e96b5>>(__acrt_lock_stream_and_call::__l2::<lambda_676bd5779251ec186b530f0a904b4b35> && setup, common_vfprintf::__l2::int <lambda>(void) & action, __acrt_lock_stream_and_call::__l2::<lambda_10027885da78ada7fb00668d7e2e96b5> && cleanup) Line 204   C++
[Inline Frame] godot.windows.opt.tools.64.exe!__acrt_lock_stream_and_call(_iobuf * const) Line 252  C++
[Inline Frame] godot.windows.opt.tools.64.exe!common_vfprintf(const unsigned __int64 options, _iobuf * const stream, const wchar_t * const format, __crt_locale_pointers * const locale, char * const arglist) Line 37  C++
godot.windows.opt.tools.64.exe!__stdio_common_vfwprintf(unsigned __int64 options, _iobuf * stream, const wchar_t * format, __crt_locale_pointers * locale, char * arglist) Line 73  C++
[External Code] 
godot.windows.opt.tools.64.exe!WindowsTerminalLogger::logv(const char * p_format, char * p_list, bool p_err) Line 63    C++
godot.windows.opt.tools.64.exe!Logger::logf_error(const char * p_format, ...) Line 122  C++
godot.windows.opt.tools.64.exe!WindowsTerminalLogger::log_error(const char * p_function, const char * p_file, int p_line, const char * p_code, const char * p_rationale, Logger::ErrorType p_type) Line 133 C++
godot.windows.opt.tools.64.exe!CompositeLogger::log_error(const char * p_function, const char * p_file, int p_line, const char * p_code, const char * p_rationale, Logger::ErrorType p_type) Line 284   C++
godot.windows.opt.tools.64.exe!_err_print_error(const char * p_function, const char * p_file, int p_line, const char * p_error, const char * p_message, ErrorHandlerType p_type) Line 79    C++
godot.windows.opt.tools.64.exe!_err_print_index_error(const char * p_function, const char * p_file, int p_line, __int64 p_index, __int64 p_size, const char * p_index_str, const char * p_size_str, const char * p_message, bool fatal) Line 110    C++
godot.windows.opt.tools.64.exe!RichTextLabel::_process_line(RichTextLabel::ItemFrame * p_frame, const Vector2 & p_ofs, int & y, int p_width, int p_line, RichTextLabel::ProcessMode p_mode, const Ref<Font> & p_base_font, const Color & p_base_color, const Color & p_font_color_shadow, bool p_shadow_as_outline, const Vector2 & shadow_ofs, const Vector2i & p_click_pos, RichTextLabel::Item * * r_click_item, int * r_click_char, bool * r_outside, int p_char_count) Line 930    C++
godot.windows.opt.tools.64.exe!RichTextLabel::_notification(int p_what) Line 1072   C++
godot.windows.opt.tools.64.exe!RichTextLabel::_notificationv(int p_notification, bool p_reversed) Line 38   C++
godot.windows.opt.tools.64.exe!Object::notification(int p_notification, bool p_reversed) Line 929   C++
godot.windows.opt.tools.64.exe!CanvasItem::_update_callback() Line 456  C++
godot.windows.opt.tools.64.exe!MethodBind0<CanvasItem>::call(Object * p_object, const Variant * * p_args, int p_arg_count, Variant::CallError & r_error) Line 148   C++
godot.windows.opt.tools.64.exe!Object::call(const StringName & p_method, const Variant * * p_args, int p_argcount, Variant::CallError & r_error) Line 918   C++
godot.windows.opt.tools.64.exe!MessageQueue::_call_function(Object * p_target, const StringName & p_func, const Variant * p_args, int p_argcount, bool p_show_error) Line 241   C++
godot.windows.opt.tools.64.exe!MessageQueue::flush() Line 301   C++
godot.windows.opt.tools.64.exe!SceneTree::idle(float p_time) Line 605   C++
godot.windows.opt.tools.64.exe!Main::iteration() Line 2298  C++
godot.windows.opt.tools.64.exe!OS_Windows::run() Line 3506  C++
godot.windows.opt.tools.64.exe!widechar_main(int argc, wchar_t * * argv) Line 176   C++
godot.windows.opt.tools.64.exe!_main() Line 200 C++
godot.windows.opt.tools.64.exe!main(int _argc, char * * _argv) Line 210 C++

In regards to the RichTextLabel::_process_line function it will throw the error from the following line:

if (p_mode != PROCESS_CACHE) {
        ERR_FAIL_INDEX_V(line, l.offset_caches.size(), 0);
        line_ofs = l.offset_caches[line];
    }
DataPlusProgram commented 2 years ago

I have created a minimal reproduction project for this issue.

In order to see the issue enable the plugin and make sure that the Godot editor output console is visible. After a few seconds it will start producing the error.

Note that if the editors output is not visible the error won't occur but the editor will soon freeze once it's visible.

The error is produced by calling this function within a thread created by the plugin:

func printOut():
    while(true):
        print("print out ------------------------------------")
        OS.delay_msec(1)

Note that decreasing the delay will cause the output text to become increasingly more garbled

richTextError.zip

balloonpopper commented 2 years ago

I've hit what looks to be this problem in 3.5 on Windows. After having my program lock up pretty consistently (it fails when I hit an "export" button in my project ~90% of the time) and not being able to see the error, I went back to 3.4.4 and saw the symptoms described above in the debug console. The same as someone else mentioned above, my project is running in tool mode, and the failing code runs in a thread. The Godot process fills the ram until I kill it, and I've got the garbled text followed by infinitely looping "out of bounds" error messages.

Eoin-ONeill-Yokai commented 2 years ago

I wonder if using call_deferred instead of call in the MessageQueue would help here. I can't help but wonder if there's some kind of String-based data race happening here where the memory gets garbled before it reaches the rich text. It might be worth a test in the next few days.

vvwx commented 2 years ago

I am running into the same issue.

My minimal reproduction project does not contain any scenes, scripts, exporting, or anything with threads. It is three nearly empty resource files and a project.godot

Godot version

Tested on both Mac and Linux

Reproduced with

Unable to reproduce with

System information Mac M1 Ubuntu 20.04.1

Steps to reproduce

  1. Extract the zip file somewhere, and cd into it

  2. Clear the cache and launch the editor from the command line

    • Mac

      rm -rf ~/Library/Caches/Godot
      /path/to/Godot -v --path . --editor
    • Linux

      rm -rf ~/.cache/godot
      /path/to/Godot_v3.5-stable_x11.64 -v --path . --editor
  3. In the editor, click on Output to view the output. You should see something similar to this.

    Godot Engine v3.5.stable.official (c) 2007-2022 Juan Linietsky, Ariel Manzur & Godot Contributors.
    Loaded builtin certs
    --- GDScript language server started ---
    EditorSettings: Save OK!
    Loading resource: res://dynamicfont.tres
    Loading resource: res://dynamicfontdata1.tres 
    Loading resource: res://dynamicfontdata2.tres
    Loading resource: res://dynamicfontdata1.tres
    Loading resource: res://dynamicfontdata2.tres
    • The Output window must remain open to reproduce the bug, so leave it open.
  4. Right click on dynamicfont.tres, then choose "Duplicate" and give it a different name.

    • You may have to do this several times (usually less than ten times, if it'll repro). On Mac I've had the best success; where duplicating dynamicfont.tres just once reproduces the problem. On Linux I've had less luck, where I'd have to duplicate dynamicfont.tres (or any of the duplicates) 5 to 10 times (and even quit the editor, clear the cache, and restart the editor) before the bug occurs.
  5. Watch the editor freeze.

  6. This error message is spammed in the terminal

    ERROR: Index line = 0 is out of bounds (l.offset_caches.size() = 0).
       at: _process_line (scene/gui/rich_text_label.cpp:168)

Video (from Mac, but similar is seen on Linux) https://user-images.githubusercontent.com/109488824/189353599-4b3b4373-d20c-471e-9cc7-1c54aeadcdbe.mp4

Minimal reproduction project DynamicFontInfiniteLoop.zip

Notes

Eoin-ONeill-Yokai commented 1 year ago

I'm unable to reproduce this on master when building for x64, but it's pretty consistently cropping up when building and running the x32 version on Windows.

akien-mga commented 1 year ago

I'm unable to reproduce this on master when building for x64, but it's pretty consistently cropping up when building and running the x32 version on Windows.

Just to be clear, do you mean that it's reproducible for a Win32 x86_32 build of the master branch? So far the results were only about 3.x and RichTextLabel has been significantly refactored in master, so I guess we assumed it fixed in 4.0. CC @bruvzg @Paulb23

Eoin-ONeill-Yokai commented 1 year ago

I'm unable to reproduce this on master when building for x64, but it's pretty consistently cropping up when building and running the x32 version on Windows.

Just to be clear, do you mean that it's reproducible for a Win32 x86_32 build of the master branch? So far the results were only about 3.x and RichTextLabel has been significantly refactored in master, so I guess we assumed it fixed in 4.0. CC @bruvzg @Paulb23

@akien-mga I'll give it more testing later, but I seemed to be getting a pretty consistent crash on x86_32 build on my 64bit Windows when using master when trying one of the user's provided test project -- though the importance of this is debatable. I'll provide the backtrace when I give it more testing.

I'm not entirely sure this is a RichTextLabel / Godot problem or perhaps just a problem with the users test file as a whole (doing something weird, causing a data race which results in undefined behavior) though so I'll also look through the test project more.

Eoin-ONeill-Yokai commented 1 year ago

@akien-mga Ah, the error on master is actually caused by improper cleanliness of threads in DataPlusProgram's example project. In their example, the thread should probably be stored as a member of the plugin so that it doesn't go out of scope and get (eventually) cleaned up.

So it's worth noting that particular example project might not be an accurate test.

DataPlusProgram commented 1 year ago

could you clarify what would be the correct way to handle this as I have moved the scope of the thread but I still see the same issues:

tool
extends EditorPlugin
var thread = Thread.new()

func printOut():
    while(true):
        print("print out ------------------------------------")
        OS.delay_msec(1)

func _ready():
    thread.start(self, "printOut")
Eoin-ONeill-Yokai commented 1 year ago

could you clarify what would be the correct way to handle this as I have moved the scope of the thread but I still see the same issues:

Is this on 4.0 (master branch / alpha) or is this a 3.x specific issue?

I think the confusion right now is around which versions have had this issue. Judging by the gdscript example, this still looks like a 3.X related issue. I'll double back and check 3.X to see if I can find a solution that doesn't involve bundling all the changes made in 4.X. As far as I could tell, this issue is now gone in 4.X.

And yeah that should be correct now.

DataPlusProgram commented 1 year ago

Yes it's 3.x and still produces the same errors as a mentioned previously.