Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segfault trying to print error in SelfList<DynamicFont>::List::~List() while closing #21060

Closed
akien-mga opened this issue Aug 15, 2018 · 7 comments

Comments

@akien-mga
Copy link
Member

akien-mga commented Aug 15, 2018

Godot version:
3.0.6, master (1c17c2b)

OS/device including version:
Mageia 6 x86_64

Issue description:
Under certain conditions, Godot (both editor and runtime) can segfault when closing with this kind of backtrace:

(gdb) bt
#0  0x00000000040ce35f in OS::print_error (this=0x0, p_function=0x4ed3e6b <SelfList<DynamicFont>::List::~List()::__FUNCTION__> "~List", p_file=0x4ed365d "core/self_list.h", p_line=111, 
    p_code=0x4ed3a90 "Condition ' _first != __null ' is true.", p_rationale=0x4f6c6aa "", p_type=Logger::ERR_ERROR) at core/os/os.cpp:88
#1  0x0000000003f8e6f5 in _err_print_error (p_function=0x4ed3e6b <SelfList<DynamicFont>::List::~List()::__FUNCTION__> "~List", p_file=0x4ed365d "core/self_list.h", p_line=111, 
    p_error=0x4ed3a90 "Condition ' _first != __null ' is true.", p_type=ERR_HANDLER_ERROR) at core/error_macros.cpp:84
#2  0x0000000003095c9a in SelfList<DynamicFont>::List::~List (this=0x579d450 <DynamicFont::dynamic_fonts>, __in_chrg=<optimized out>) at core/self_list.h:111
#3  0x00007ffff5087468 in __run_exit_handlers () from /lib64/libc.so.6
#4  0x00007ffff50874b5 in exit () from /lib64/libc.so.6
#5  0x00007ffff5071607 in __libc_start_main () from /lib64/libc.so.6
#6  0x0000000000f08579 in _start () at ../sysdeps/x86_64/start.S:118

The issue seems to be a race condition where OS can get freed before SelfList<DynamicFont>::List::~List() runs, and as the latter tries to emit an error message via OS::print_error, it crashes.

Steps to reproduce:
(Weird test case but that's what you get with good QA testers :)).

  • Download this demo, compatible with Godot 3.0 and 3.1-dev.
  • In the demo folder, run godot "2D Kinematic Collision Demo", it should crash:
ERROR: _load: Method/Function Failed, returning: RES()
   At: core/io/resource_loader.cpp:186.
ERROR: start: Condition ' !scene ' is true. returned: false
   At: main/main.cpp:1686.
WARNING: cleanup: ObjectDB Instances still exist!
   At: core/object.cpp:1989.
ERROR: clear: Resources Still in use at Exit!
   At: core/resource.cpp:418.
Segmentation fault (core dumped)

Minimal reproduction project:
Demo, see above steps to reproduce for one way to trigger this issue (there are more).

@akien-mga akien-mga added this to the 3.1 milestone Aug 15, 2018
@akien-mga
Copy link
Member Author

I assume that this should be investigated in:

  • scene/resources/dynamic_font.cpp
  • main/main.cpp
  • core/list.h
  • core/error_macros.{cpp,h}

@API-Beast
Copy link

API-Beast commented Aug 23, 2018

Ran into the same issue. (Windows, 3.0.6)

I wonder what causes the error printed in the first place?

The error message "Condition ' _first != 0 ' is true." isn't very descriptive, and it always happens in a SelfList<DynamicFont>, some faulty deinitialization code perhaps? Why is it expecting it to be null in the first place?

Edit - When running my project I have two more errors of the same kind, before OS is deinitalized. One for SelfList<GDScriptFunction> and one for SelfList<GDScript>, so this doesn't seem to be isolated case. (Though the only one that happens too late to log it.)

Edit 2 - Found the culprit.

scene/resources/dynamic_font.h:288

static SelfList<DynamicFont>::List dynamic_fonts;

Due to being static it will be deinitalized too late. That said, I think the error message is misplaced, since there isn't really anything special going on here that could have been done wrong.

@reduz
Copy link
Member

reduz commented Sep 7, 2018

Somehow it seems this error is back.. this is quite an interesting challenge due to everything seeming fine with it.

@viktor-ferenczi
Copy link
Contributor

Got these assertion failures on the console in Godot 3.0.6 on Windows 64 bit while working on reducing the resolution of images inside my project:

ERROR: ~List: Condition ' _first != __null ' is true.
   At: core/self_list.h:100
ERROR: ~List: Condition ' _first != __null ' is true.
   At: core/self_list.h:100

Godot did not crash, but it was frozen for 20+ seconds when I deleted a folder in Godot's UI. I got the above errors on the console before I attempted to delete the folder.

I will post here if/when I will have a systematic way to reproduce it.

@akien-mga
Copy link
Member Author

It's related (potentially a duplicate, but not sure yet) to #18429. Whenever we leak resources on close (as apparently the case here with dynamic fonts), the logger can crash because it tries to print errors after the deletion of the logger singleton.

@akien-mga
Copy link
Member Author

Simple project that reproduces the bug: CleanupSegfault-DynamicFont.zip

On Linux, if you run via a debug binary, it hangs on close.
If you run via a release binary, it segfaults.
If you run via a debug binary in gdb, it segfaults. (So not sure what the hang is - infinite loop in the crash handler?)

@akien-mga
Copy link
Member Author

I'm pretty confident that this is a duplicate of #18429 now (or a subset of it at least), so closing.

mjtorn pushed a commit to mjtorn/godot that referenced this issue Oct 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants