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

Make push_error and push_warning print name of calling function #93648

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

TV4Fun
Copy link

@TV4Fun TV4Fun commented Jun 27, 2024

Currently, push_error and push_warning give themselve as the calling
function, which is not useful for debugging. I have altered these to use the
C stacktrace to get the name of the function that called them. This saves
having to turn these functions into macros, which would require recompiling
every single piece of code that uses them. I have also set it to, when debug
symbols are available, use them with atos (available on macOS) to find the
exact source file and line being called from. It should be possible to the same
thing on Linux using addr2line, but I don't have a Linux box handy to test
that. I am not sure how you would implement this in Windows.

I have tested this on macOS Sonoma 14.5 (23F79). It should work on any *nix
system. I am not sure about Windows.

Fixes #76770

QOL improvement to allow direct construction of `List`s.
Currently, `push_error` and `push_warning` give themselve as the calling
function, which is not useful for debugging. I have altered these to use the
C stacktrace to get the name of the function that called them. This saves
having to turn these functions into macros, which would require recompiling
every single piece of code that uses them. I have also set it to, when debug
symbols are available, use them with `atos` (available on macOS) to find the
exact source file and line being called from. It should be possible to the same
thing on Linux using `addr2line`, but I don't have a Linux box handy to test
that. I am not sure how you would implement this in Windows.

I have tested this on macOS Sonoma 14.5 (23F79). It should work on any *nix
system. I am not sure about Windows.

Fixes godotengine#76770
@TV4Fun TV4Fun requested a review from a team as a code owner June 27, 2024 05:17
@Mickeon Mickeon added this to the 4.x milestone Jun 27, 2024
@Mickeon
Copy link
Contributor

Mickeon commented Jun 27, 2024

Could you provide screenshots on how this would look now?

Also check out the static check errors.

Copy link
Member

@AThousandShips AThousandShips left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be done in a platform independent fashion, you need to fix the style issues so the CI can run to verify it on all platforms, but this would need to run on all platforms with reasonable support IMO, or be put just in the specific platform

core/templates/list.h Outdated Show resolved Hide resolved
@AThousandShips
Copy link
Member

AThousandShips commented Jun 27, 2024

Also I'm not sure this change makes sense, this method is called from scripting, the GDScript method won't be shown, so please add some screenshots to see what this outputs

We don't want it to print the c++ method that called into scripting IMO

@TV4Fun TV4Fun requested review from a team as code owners June 28, 2024 04:51
@TV4Fun
Copy link
Author

TV4Fun commented Jun 28, 2024

Okay, I have fixed the formatting and code style issues, moved the platform dependent code into relevant subclasses of OS, and fixed it so that it now properly reports the stack trace when called from scripts. This is only implemented for macOS for now as that is the system I have available. The Linux implementation should be similar except that retrieving debug symbols should be done with addr2line instead of atos. I am not sure exactly how to implement this on Windows, so perhaps someone with more knowledge of Windows debugging could contribute that part.

To clarify, there are two cases this fix covers:

  1. push_error/push_warning are called from GDScript code This appears to have been partially implemented in the debugger for runtime code, but still fails for editor code. I have added code to retrieve the script callstack modeled after what RemoteDebugger::_err_handler does. In order for this to work requires that DEBUG_ENABLED be defined (true by default for editor and template_debug targets), and that Godot is run with the --debug flag.
  2. push_error/push_warning are called from C++ code This can be from within the Godot engine or from GDExtension/GDNative code. This requires retrieving the C++ callstack. Getting source filenames and line numbers requires that the assembly generating the message was compiled with debug symbols. If debug symbols are not available, it can still usually get the name of the function that produced the message, which is much more useful than what is currently availble.

Current behavior

Runtime GDScript

As I said, this is partially implemented already, but still includes an unhelpful reference to variant_utility.cpp that is now fixed. Here is how it looked with a warning generated from a GDScript file before in debugger:

Screenshot 2024-06-27 at 10 14 14 PM

Editor GDScript

GDScript run in the editor did not properly show where it was called from before, either in the editor logger or to stdout. Here is the view from the editor:

Screenshot 2024-06-27 at 10 13 01 PM

and here is the view from stdout (with Rider):

Screenshot 2024-06-27 at 10 13 08 PM

C++

Here is a warning generated from godot-git-plugin in the editor logger:

Screenshot 2024-06-27 at 10 13 35 PM

and the view from stdout:

Screenshot 2024-06-27 at 10 13 43 PM

Proposed improvements

Runtime GDScript

Screenshot 2024-06-27 at 11 16 41 PM Screenshot 2024-06-27 at 10 32 10 PM

Editor GDScript

View in editor logger:
Screenshot 2024-06-27 at 10 16 50 PM

View in stdout:

Screenshot 2024-06-27 at 10 17 06 PM

C++

View in editor logger:

Screenshot 2024-06-27 at 10 17 39 PM

View in stdout:

Screenshot 2024-06-27 at 10 17 58 PM

There are I'm sure still ways to make the results look a little better. All of the various logger implementations seem to have different ideas of what the two different string arguments to errfunc are for, which makes it hard to create a unified implementation that gives the relevant information without giving extra irrelevant information. I will happily accept any contributions anyone else wants to make to improve the output formatting.

The Linux build breaks on `OS_Unix` because `Dl_info` is not `typedef`ed as
`struct dl_info`, so the forward declaration of that struct breaks. Changing
the forward declaration to `struct Dl_info` breaks the Mac build though, so
that leaves us with some `#ifdef`s. This may or may not work, I'll have to see.
Okay, there doesn't actually seem to be a way to forward declare a `typedef`
to an anonymous `struct`. So, rather than include an unnecessary system header
in `os_unix.h`, I am now just passing the members of `Dl_info` individually.
This will be slightly less efficient, but this code is generally not called
in performance-critical paths, and this should be clean, maintainable, and
platform-independent.
Neither Android's NDK nor Emscripten provide `backtrace` through `execinfo.h`.
There are other ways to get a stacktrace on these platforms, but I am not
expert enough to implement them, so leave them unimplemented for now.
@Calinou
Copy link
Member

Calinou commented Jun 28, 2024

Would #91006 be of any use here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

push_error/warning should print GDScript line, not C++
4 participants