godot icon indicating copy to clipboard operation
godot copied to clipboard

Make `push_error` and `push_warning` print name of calling function

Open TV4Fun opened this issue 1 year ago • 4 comments

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

TV4Fun avatar Jun 27 '24 05:06 TV4Fun

Could you provide screenshots on how this would look now?

Also check out the static check errors.

Mickeon avatar Jun 27 '24 08:06 Mickeon

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

AThousandShips avatar Jun 27 '24 09:06 AThousandShips

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.

TV4Fun avatar Jun 28 '24 05:06 TV4Fun

Would https://github.com/godotengine/godot/pull/91006 be of any use here?

Calinou avatar Jun 28 '24 16:06 Calinou

Would #91006 be of any use here?

Yes, that looks like it would do very much the same thing as what I do for GDScript stacktraces. Though theirs is a much more sweeping change, and mine is much more targeted. Mine requires being run in debug mode to get an accurate GDScript backtraces, while theirs completely rewrites GDScript's stack system to be fast enough to run all the time. There are pros and cons to both approaches.

One thing my PR does that theirs doesn't is print the C++ stacktrace, which is still needed if push_warning or push_error are called from C++ code.

TV4Fun avatar Jul 02 '24 04:07 TV4Fun

Precisely these days I'm trying to hunt down the root trigger of certain operations and the ability to obtain a proper C++ stack trace would come super handy.

Regarding the implementation, I'd just like to point out that the various handle_crash() implementations already contain code for stack trace collection. I'd say this PR would need to refactor those pieces out into individual functions instead of adding its own.

RandomShaper avatar Jul 03 '24 08:07 RandomShaper

Precisely these days I'm trying to hunt down the root trigger of certain operations and the ability to obtain a proper C++ stack trace would come super handy.

Regarding the implementation, I'd just like to point out that the various handle_crash() implementations already contain code for stack trace collection. I'd say this PR would need to refactor those pieces out into individual functions instead of adding its own.

@RandomShaper Yes, just looking at the MacOS implementation, there is definitely a lot of overlap in functionality that could be moved into a separate library to save some duplication. If you would like to contribute a refactor to do that, you are more than welcome to. Personally, I am happy with this version and need to move on to other projects.

TV4Fun avatar Jul 04 '24 03:07 TV4Fun

@RandomShaper Yes, just looking at the MacOS implementation, there is definitely a lot of overlap in functionality that could be moved into a separate library to save some duplication. If you would like to contribute a refactor to do that, you are more than welcome to. Personally, I am happy with this version and need to move on to other projects.

Would it be fine with you that someone (possibly me when I can spend time on this) takes over your PR? That would mean that other contributor would take your changes, apply the refactor and commit them to a new PR superseding this one, crediting both authors (by having separate commits if it makes sense for the repo or using a co-author annotation).

RandomShaper avatar Jul 04 '24 08:07 RandomShaper

@RandomShaper Yes, just looking at the MacOS implementation, there is definitely a lot of overlap in functionality that could be moved into a separate library to save some duplication. If you would like to contribute a refactor to do that, you are more than welcome to. Personally, I am happy with this version and need to move on to other projects.

Would it be fine with you that someone (possibly me when I can spend time on this) takes over your PR? That would mean that other contributor would take your changes, apply the refactor and commit them to a new PR superseding this one, crediting both authors (by having separate commits if it makes sense for the repo or using a co-author annotation).

Yes, that would be fine. Just give me credit in some way.

TV4Fun avatar Jul 04 '24 09:07 TV4Fun

This is something I would really like to add to #91006 to make it more complete (my PR fixes a number of issues in GDScript and also makes it work properly outside the debugger, as well as making the log system support it properly too).

The problem is that It's kind of only usable for desktop, afaik on mobile and other platforms there is no implementation to get the C stack.

reduz avatar Jul 10 '24 10:07 reduz