Pyrogenesis HEAD
Pyrogenesis, a RTS Engine
|
#include "precompiled.h"
#include "lib/debug.h"
#include "lib/alignment.h"
#include "lib/app_hooks.h"
#include "lib/fnv_hash.h"
#include "lib/sysdep/sysdep.h"
#include "lib/sysdep/vm.h"
#include <cstdarg>
#include <cstring>
#include <cstdio>
Classes | |
class | PrintfWriter |
Namespaces | |
namespace | anonymous_namespace{debug.cpp} |
Enumerations | |
enum | SkipStatus { INVALID , VALID , BUSY } |
Functions | |
STATUS_ADD_DEFINITIONS (debugStatusDefinitions) | |
void | debug_filter_add (const char *tag) |
debug output is very useful, but "too much of a good thing can kill you". More... | |
void | debug_filter_remove (const char *tag) |
in future, discard output with the given tag. More... | |
void | debug_filter_clear () |
clear all filter state; equivalent to debug_filter_remove for each tag that was debug_filter_add-ed. More... | |
bool | debug_filter_allows (const char *text) |
indicate if the given text would be printed. More... | |
void | debug_printf (const char *fmt,...) |
write a formatted string to the debug channel, subject to filtering (see below). More... | |
void | debug_puts_filtered (const char *text) |
call debug_puts if debug_filter_allows allows the string. More... | |
Status | debug_WriteCrashlog (const wchar_t *text) |
const wchar_t * | debug_BuildErrorMessage (const wchar_t *description, const wchar_t *filename, int line, const char *func, void *context, const wchar_t *lastFuncToSkip) |
build a string describing the given error. More... | |
void | debug_DisplayMessage (const wchar_t *caption, const wchar_t *msg) |
translates and displays the given strings in a dialog. More... | |
static bool | ShouldSuppressError (std::atomic< bool > *suppress) |
static ErrorReactionInternal | CallDisplayError (const wchar_t *text, size_t flags) |
static ErrorReaction | PerformErrorReaction (ErrorReactionInternal er, size_t flags, std::atomic< bool > *suppress) |
ErrorReaction | debug_DisplayError (const wchar_t *description, size_t flags, void *context, const wchar_t *lastFuncToSkip, const wchar_t *pathname, int line, const char *func, std::atomic< bool > *suppress) |
display an error dialog with a message and stack trace. More... | |
void | debug_SkipErrors (Status err) |
suppress (prevent from showing) the error dialog from subsequent debug_OnError for the given Status. More... | |
size_t | debug_StopSkippingErrors () |
static bool | ShouldSkipError (Status err) |
ErrorReaction | debug_OnError (Status err, std::atomic< bool > *suppress, const wchar_t *file, int line, const char *func) |
called when a DEBUG_WARN_ERR indicates an error occurred; notifies the user via debug_DisplayError. More... | |
ErrorReaction | debug_OnAssertionFailure (const wchar_t *expr, std::atomic< bool > *suppress, const wchar_t *file, int line, const char *func) |
called when a ENSURE/ASSERT fails; notifies the user via debug_DisplayError. More... | |
Variables | |
constexpr std::size_t | anonymous_namespace{debug.cpp}::MESSAGE_SIZE = 512 * KiB / sizeof(wchar_t) |
wchar_t | anonymous_namespace{debug.cpp}::g_MessageBuffer [MESSAGE_SIZE] |
static const StatusDefinition | debugStatusDefinitions [] |
static const size_t | MAX_TAGS = 20 |
static u32 | tags [MAX_TAGS] |
static size_t | num_tags |
static std::atomic< bool > | isExiting { false } |
static std::atomic< SkipStatus > | skipStatus { INVALID } |
static Status | errorToSkip |
static size_t | numSkipped |
enum SkipStatus |
|
static |
const wchar_t * debug_BuildErrorMessage | ( | const wchar_t * | description, |
const wchar_t * | fn_only, | ||
int | line, | ||
const char * | func, | ||
void * | context, | ||
const wchar_t * | lastFuncToSkip | ||
) |
build a string describing the given error.
this is a helper function used by debug_DumpStack and is made available so that the self-test doesn't have to display the error dialog.
description | general description of the problem. |
fn_only | filename (no path) of source file that triggered the error. |
line,func | exact position of the error. |
context,lastFuncToSkip | see debug_DumpStack. |
ErrorReaction debug_DisplayError | ( | const wchar_t * | description, |
size_t | flags, | ||
void * | context, | ||
const wchar_t * | lastFuncToSkip, | ||
const wchar_t * | file, | ||
int | line, | ||
const char * | func, | ||
std::atomic< bool > * | suppress | ||
) |
display an error dialog with a message and stack trace.
description | text to show. |
flags | see DebugDisplayErrorFlags. |
context,lastFuncToSkip | see debug_DumpStack. |
file,line,func | location of the error (typically passed as WIDEN(FILE), LINE, func from a macro) |
suppress | pointer to a caller-allocated flag that can be used to suppress this error. if NULL, this functionality is skipped and the "Suppress" dialog button will be disabled. note: this flag is read and written exclusively here; caller only provides the storage. |
void debug_DisplayMessage | ( | const wchar_t * | caption, |
const wchar_t * | msg | ||
) |
translates and displays the given strings in a dialog.
this is typically only used when debug_DisplayError has failed or is unavailable because that function is much more capable. implemented via sys_display_msg; see documentation there.
void debug_filter_add | ( | const char * | tag | ) |
debug output is very useful, but "too much of a good thing can kill you".
we don't want to require different LOGn() macros that are enabled depending on "debug level", because changing that entails lengthy compiles and it's too coarse-grained. instead, we require all strings to start with "tag_string|" (exact case and no quotes; the alphanumeric-only <tag_string> identifies output type). they are then subject to filtering: only if the tag has been "added" via debug_filter_add is the appendant string displayed.
this approach is easiest to implement and is fine because we control all logging code. LIMODS falls from consideration since it's not portable and too complex.
notes:
in future, allow output with the given tag to proceed. no effect if already added.
bool debug_filter_allows | ( | const char * | text | ) |
indicate if the given text would be printed.
useful for a series of debug_printfs - avoids needing to add a tag to each of their format strings.
void debug_filter_clear | ( | ) |
clear all filter state; equivalent to debug_filter_remove for each tag that was debug_filter_add-ed.
void debug_filter_remove | ( | const char * | tag | ) |
in future, discard output with the given tag.
no effect if not currently added.
ErrorReaction debug_OnAssertionFailure | ( | const wchar_t * | assert_expr, |
std::atomic< bool > * | suppress, | ||
const wchar_t * | file, | ||
int | line, | ||
const char * | func | ||
) |
called when a ENSURE/ASSERT fails; notifies the user via debug_DisplayError.
assert_expr | the expression that failed; typically passed as #expr in the assert macro. |
suppress | see debug_DisplayError. |
file,line | source file name and line number of the spot that failed |
func | name of the function containing it |
ErrorReaction debug_OnError | ( | Status | err, |
std::atomic< bool > * | suppress, | ||
const wchar_t * | file, | ||
int | line, | ||
const char * | func | ||
) |
called when a DEBUG_WARN_ERR indicates an error occurred; notifies the user via debug_DisplayError.
err | Status value indicating the error that occurred |
suppress | see debug_DisplayError. |
file,line | source file name and line number of the spot that failed |
func | name of the function containing it |
void debug_printf | ( | const char * | fmt, |
... | |||
) |
write a formatted string to the debug channel, subject to filtering (see below).
implemented via debug_puts - see performance note there.
fmt | Format string and varargs; see printf. |
void debug_puts_filtered | ( | const char * | text | ) |
call debug_puts if debug_filter_allows allows the string.
void debug_SkipErrors | ( | Status | err | ) |
suppress (prevent from showing) the error dialog from subsequent debug_OnError for the given Status.
rationale: for edge cases in some functions, warnings are raised in addition to returning an error code. self-tests deliberately trigger these cases and check for the latter but shouldn't cause the former. we therefore need to squelch them.
err | the Status to skip. |
note: only one concurrent skip request is allowed; call debug_StopSkippingErrors before the next debug_SkipErrors.
size_t debug_StopSkippingErrors | ( | ) |
Status debug_WriteCrashlog | ( | const wchar_t * | text | ) |
|
static |
|
static |
|
static |
STATUS_ADD_DEFINITIONS | ( | debugStatusDefinitions | ) |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |
|
static |