Tech/LxEngine/Errors and Messages
From Athile
This page is a work-in-progress. It is not yet complete.
It may contain inaccurate, incorrect information. Use at your own risk.
It may contain inaccurate, incorrect information. Use at your own risk.
Notes
80/20 rule. These rules apply in most cases, and if you're not sure, then yes they should. However, there are exceptions: for example, in performance-sensitive code.
5 Levels:
- Message - generally technical, but user visible message intended for std::cout, the application console, etc. Also sent to the log file
- Log - sent to the log file variation
- Warning - sent to the log file and the debugger (if possible)
- Error - sent to the log file, an exception is raised, should add details and rethrow; can catch if can be handled safely
- Fatal - sent to log file, exception raised, should save app critical data and exit asap
variations:
- debug_message - same as message but only compiled into debug builds
- log_once, warn_once, message_once - same as normal, but will only write the message the first time that line of code is hit
lx_debug() lx_message() lx_log() lx0::error_exception() lx0::fatal_exception() macro lx_error_exception() macro lx_fatal_exception() macro lx_assert() macro lx_check_error() macro lx_check_fatal() macro lx_check_warn() macro lx_assert_not_reentrant();
Error Handling
In non-performance critical code, errors should be handled as exceptions. Return values should be reserved for behavior when the function is executed within it's defined domain.
- lx0::error_exception should be used for errors that, while unexpected, as possibly recoverable.
- lx0::fatal_exception should be used for errors that indicate the application should shutdown as soon as possible to avoid data corruption or loss. These exceptions should not be caught, unless to save critical data and then be rethrown.
Individual parts of the code may choose to sub-class error_exception to allow specific types of errors to be caught by different handlers.
The common error handling code should:
- Catch the error_exception
- Call error_exception::detail() to add details about where this error is occuring
- Clean-up any local state to deal with the error
- Re-throw unless the error can be handled completely and with certainty. When in doubt rethrow!
Checklist
if something not really expected happens: if in a destructor: Don't throw an exception!!! Log a warning Handle it as gracefully as possible Save critical data if necessary else switch (what happened) case A Common, Obvious Error: case Something Valid But Nonsensical: warning; case Misuse of the API: case Input data malformed: case User data doesn't make sense: case Parsing Error: throw error_exception case Out of Memory: free as much non-critical memory as possible throw error_exception; case Hardware Error: possibly retry once or twice; salvage system critical data throw lx0::fatal_exception case Threading Error: default: salvage system critical data throw lx0::fatal_exception;