diff --git a/lib/framework/debug.cpp b/lib/framework/debug.cpp index 3d661b6c8..b17484f66 100644 --- a/lib/framework/debug.cpp +++ b/lib/framework/debug.cpp @@ -40,8 +40,6 @@ #include // Nonfatal runtime backtraces. #endif //WZ_OS_LINUX -extern void NotifyUserOfError(char *); // will throw up a notifier on error - #define MAX_LEN_LOG_LINE 512 char last_called_script_event[MAX_EVENT_NAME_LEN]; @@ -376,6 +374,24 @@ void _realObjTrace(int id, const char *function, const char *str, ...) printToDebugCallbacks(outputBuffer); } +// Thread local to prevent a race condition on read and write to this buffer if multiple +// threads log errors. This means we will not be reporting any errors to console from threads +// other than main. If we want to fix this, make sure accesses are protected by a mutex. +static WZ_DECL_THREAD char errorStore[512]; +static WZ_DECL_THREAD bool errorWaiting = false; +const char *debugLastError() +{ + if (errorWaiting) + { + errorWaiting = false; + return errorStore; + } + else + { + return NULL; + } +} + void _debug( int line, code_part part, const char *function, const char *str, ... ) { va_list ap; @@ -454,7 +470,8 @@ void _debug( int line, code_part part, const char *function, const char *str, .. if (part == LOG_ERROR) { // used to signal user that there was a error condition, and to check the logs. - NotifyUserOfError(useInputBuffer1 ? inputBuffer[1] : inputBuffer[0]); + sstrcpy(errorStore, useInputBuffer1 ? inputBuffer[1] : inputBuffer[0]); + errorWaiting = true; } // Throw up a dialog box for users since most don't have a clue to check the dump file for information. Use for (duh) Fatal errors, that force us to terminate the game. diff --git a/lib/framework/debug.h b/lib/framework/debug.h index c6c7614b8..13730328e 100644 --- a/lib/framework/debug.h +++ b/lib/framework/debug.h @@ -222,6 +222,9 @@ void debug_exit( void ); */ extern void debugFlushStderr(void); +/// Return the last set error message, or NULL is none set since last time we were called. +const char *debugLastError(); + /** * Register a callback to be called on every call to debug() * diff --git a/src/display3d.cpp b/src/display3d.cpp index 0d290ab78..c7102597d 100644 --- a/src/display3d.cpp +++ b/src/display3d.cpp @@ -133,7 +133,6 @@ static PIELIGHT getBlueprintColour(STRUCT_STATES state); static void NetworkDisplayPlainForm(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset); static void NetworkDisplayImage(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset); -void NotifyUserOfError(char *msg); extern bool writeGameInfo(const char *pFileName); // Used to help debug issues when we have fatal errors & crash handler testing. /******************** Variables ********************/ // Should be cleaned up properly and be put in structures. @@ -223,8 +222,7 @@ bool showORDERS = false; bool showLevelName = true; /** When we have a connection issue, we will flash a message on screen */ -static bool errorWaiting = false; -static char errorMessage[512]; +static const char *errorWaiting = NULL; static uint32_t lastErrorTime = 0; #define NETWORK_FORM_ID 0xFAAA @@ -338,13 +336,6 @@ static inline void rotateSomething(int &x, int &y, uint16_t angle) y = newY; } - -void NotifyUserOfError(char *msg) -{ - errorWaiting = true; - ssprintf(errorMessage, "%s", msg); -} - static Blueprint getTileBlueprint(int mapX, int mapY) { Vector2i mouse(world_coord(mapX) + TILE_UNITS/2, world_coord(mapY) + TILE_UNITS/2); @@ -751,16 +742,21 @@ void draw3DScene( void ) } if (errorWaiting) { + // print the error message if none have been printed for one minute if (lastErrorTime == 0 || lastErrorTime + (60 * GAME_TICKS_PER_SEC) < realTime) { char trimMsg[255]; audio_PlayTrack(ID_SOUND_BUILD_FAIL); - ssprintf(trimMsg, "Error! (Check your logs!): %.78s", errorMessage); + ssprintf(trimMsg, "Error! (Check your logs!): %.78s", errorWaiting); addConsoleMessage(trimMsg, DEFAULT_JUSTIFY, NOTIFY_MESSAGE); - errorWaiting = false; + errorWaiting = NULL; lastErrorTime = realTime; } } + else + { + errorWaiting = debugLastError(); + } if (showSAMPLES) //Displays the number of sound samples we currently have { iV_SetFont(font_regular);