Contributing to ENIGMA => Proposals => Topic started by: TheExDeus on December 25, 2014, 07:09:12 PM

Title: Error reporting
Post by: TheExDeus on December 25, 2014, 07:09:12 PM
I would want to start a discussion on how to improve ENIGMA's error reporting. Last changes in this respect was by Robert, who added scope tracking, so errors would tell in which event an error occurred. What we need right now is to actually show the offending line number, because usually it's not enough to see the event (because events call scripts, which then can massively big). The bug fixing right now means using GBD with "break dialogs.cpp:56" which adds a breakpoint at "show_error". Then I can backtrace to see where error originated from, but even then the information is in _IDE_EDIT files. So my ideas are these:
1) Creating a separate debugger will probably be infeasible, so we will probably have to use GDB. This means we need to integrate it in LGM, to allow breakpoints to be set and called properly. This is done via the GDB interpreter mode, which allows it to be used via the GDB/MI interface (https://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI.html#GDB_002fMI). As far as I understand it's, like using the regular console, but the output is easier to parse. So you run GDB as a separate process and then communicate with it like a cmd program.
2) We need to map the _IDE_EDIT files to original source, so we can track where in the original source something goes wrong, not the parsed IDE_EDIT. This could be done via some macro's that uses parser information to generate something like GCC does with __LINE__, __FILE__ tags. This is actually needed for GDB as well (but in reverse), because we need to be able to set breakpoints in scripts, but GDB needs to change them to be in _IDE_EDIT.

Any ideas on how to do this? This seems purely an LGM side of stuff (only the mapping has to be done something in the parser), so I'm not sure how to do this.

I know Robert did try adding the graphical part to LGM (the model dialog at the bottom) that will be useful here.

edit: Also, the current debugging described here doesn't actually work either. The line locations shown by GBD actually differ from the line locations in files. I don't know why.
Title: Re: Error reporting
Post by: Goombert on December 25, 2014, 08:00:03 PM
No no no no Harri, we don't need any of this noise.

Building the executable with debugging symbols and using the GCC compiler you can generate line numbers, file names, and a full stack trace.

Then we can implement the same thing as the LGM error reporting dialog in ENIGMA, trust me I've already done the research on this. In addition we should implement this dialog as the function show_debug_message with a texture component that lets the user cut copy and paste as well as click a button to open a web browser or something by overloading the function with a url parameter or something, or even a script index to call when the button is clicked. This is to avoid ambiguity of the show_error function, show_error should never show a stack trace it should just be a native dialog that displays the message the user specifies, show_debug_message is intended for more advanced debugging, though GM mixes it up and uses the same dialog for both which is pointless. show_error should be replaced in all of our debugging code and be made more headless.

Side Note: That's a really great idea for overloading GM's dialog functions, accept script indices as arguments to be called when buttons on the dialog are clicked instead of checking the return. I can't believe I never thought of that.

Code: (GML) [Select]
// this would allow the user to make a script for when the dialog completes that can either open a
// file, another program, or a URL in a web browser to github for instance where they could report the bug
show_debug_message(string title, string message, int reportScript);
// all of our internally detected issues would automatically set this to report to our GitHub tracker,
// but we could add an extra function that also lets the user override that like the following
set_debug_report_script(int reportScript);
// if it does not exist then we point the user to ENIGMA's GitHub issue tracker
Title: Re: Error reporting
Post by: TheExDeus on December 25, 2014, 08:31:15 PM
You are sure that works on anything other than Linux? Most of the stuff like "addr2line" is linux only as far as I see. So your idea is to put all this error reporting inside ENIGMA's engine itself? So when it crashes, it returns the stacktrace even if no LGM is running? It would be awesome, but as I said, the example you posted seems to be Linux only.

My idea was basically the same as yours, but mine used gdb (that comes with mingw) we call from LGM. We still need a way to map users to source to parsed source though. Like the stacktrace with your method would still show stuff like "C:\ProgramData\ENIGMA\Preprocessor_Environment_Editable\IDE_EDIT_objectfunctionality.h:1410" instead of "Obj_guy:create event:20" or something like that. I also found that you can just call gdb from the crashing application itself (http://stackoverflow.com/questions/3151779/how-its-better-to-invoke-gdb-from-program-to-print-its-stacktrace) which is something between what I and you are talking about. But this requires the user to have GDB and he won't be able to run the debug version otherwise. In your idea he wouldn't need gdb and in my case you run it from LGM, so you always have it.
Title: Re: Error reporting
Post by: Goombert on December 25, 2014, 08:40:58 PM
Yes essentially because GM used to be able to let the programmer show debug messages in run mode, this is great if they want this as it can make it easier for them to debug their games with users. And showing that at runtime in compiled mode can only be done without LateralGM or a plugin. The abstraction of show_debug_message and show_error was needed anyway, the first step is to make show_debug_message show the stack trace and let show_error just display the error message passed, this was a mistake I originally made because I was too lazy to replace all of our show_error calls, but I may do this sometime soon and send a pull request.

I am certain we can do this on Windows as well.

We can also make an implementation for MSVC. I think we should abstract this from the engine somehow though into our own reusable library, I am suggesting we write this and put it in a separate repository, it might actually become pretty popular since there seems to be no equivalent.

It looks like there is a project that makes this easier for MSVC.

The reason is because we also want these error messages to show when building from the Command Line Interface, the CLI should also allow setting breakpoints just as the IDE does. The point is that ENIGMA should be able to do all it can do by itself without relying on anything else. I'll try to get Josh to comment on this tonight.

At the very least we could also offer a get_backtrace() function in EDL that lets the user get the string backtrace and do with it as they please. Or actually I think GM used to have a get_debug_message() or similar for this.
Title: Re: Error reporting
Post by: Josh @ Dreamland on December 25, 2014, 09:32:20 PM
I was going to have the new parser preserve token line numbers in the code dump so that we could use the #file and #line directives. Actually, I guess the parser already does that, so the pretty printer just needs to leverage them during output. I never started the pretty printer, because the compiler wasn't mature enough. Even the parser's only like 85% done. The big block was that the newest JDI changed the lexer interface, which created some problems during port, so I tried refactoring the lexer to be more modular. This exposed some issues in the way I handle macros, so I started recoding that, and then got involved in other things (ENIGMA-related and otherwise). Maybe I'll resume work on that tomorrow night or the morning after.
Title: Re: Error reporting
Post by: TheExDeus on December 26, 2014, 09:57:04 AM
How would breakpoints work in Robert's idea? I get that we can return stacktrace from C++, but how would you set a breakpoint? In GDB I had two ideas - one is the GDB/MI interface and the other was using regular files. GDB supports stuff like gdbinit file or something, which basically lists all the commands you need when you run a gdb project. So LGM would write that file and run GDB with the game, which would load all the breakpoints from the file. Problem was still mapping the user source to parsed source, as the breakpoints need to be in the parsed source.

Anyway, I'll what Josh comes up with.
Title: Re: Error reporting
Post by: Josh @ Dreamland on December 27, 2014, 12:18:11 AM
The #file and #line directives will translate to GDB, too. With them in place, you'd literally tell gdb, break object0.create.edl:5, or whatever pseudonym is generated for event files. At worst, the compiler would spit out something like this:
Code: (C++) [Select]
#file object_index.event_index.event_id.edl
#line 0
and so you'd have to say break 0.0.0.edl:5.