diff options
Diffstat (limited to 'src/common/Debugging/Errors.cpp')
| -rw-r--r-- | src/common/Debugging/Errors.cpp | 119 |
1 files changed, 85 insertions, 34 deletions
diff --git a/src/common/Debugging/Errors.cpp b/src/common/Debugging/Errors.cpp index a455b06a32..4c97ceb675 100644 --- a/src/common/Debugging/Errors.cpp +++ b/src/common/Debugging/Errors.cpp @@ -1,37 +1,82 @@ /* - * Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-GPL2 - * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL3 v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3 + * Copyright (C) 2008-2019 TrinityCore <https://www.trinitycore.org/> * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> */ #include "Errors.h" - -#include <thread> +#include "StringFormat.h" +#include <cstdio> #include <cstdlib> +#include <thread> +#include <cstdarg> -namespace Trinity { +/** + @file Errors.cpp -void Assert(char const* file, int line, char const* function, char const* message) -{ - fprintf(stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s\n", - file, line, function, message); - *((volatile int*)NULL) = 0; + @brief This file contains definitions of functions used for reporting critical application errors + + It is very important that (std::)abort is NEVER called in place of *((volatile int*)NULL) = 0; + Calling abort() on Windows does not invoke unhandled exception filters - a mechanism used by WheatyExceptionReport + to log crashes. exit(1) calls here are for static analysis tools to indicate that calling functions defined in this file + terminates the application. + */ + +#if PLATFORM == PLATFORM_WINDOWS +#include <Windows.h> +#define Crash(message) \ + ULONG_PTR execeptionArgs[] = { reinterpret_cast<ULONG_PTR>(strdup(message)), reinterpret_cast<ULONG_PTR>(_ReturnAddress()) }; \ + RaiseException(EXCEPTION_ASSERTION_FAILURE, 0, 2, execeptionArgs); +#else +// should be easily accessible in gdb +extern "C" { char const* TrinityAssertionFailedMessage = nullptr; } +#define Crash(message) \ + TrinityAssertionFailedMessage = strdup(message); \ + *((volatile int*)nullptr) = 0; \ exit(1); +#endif + +namespace +{ + std::string FormatAssertionMessage(char const* format, va_list args) + { + std::string formatted; + va_list len; + + va_copy(len, args); + int32 length = vsnprintf(nullptr, 0, format, len); + va_end(len); + + formatted.resize(length); + vsnprintf(&formatted[0], length + 1, format, args); + + return formatted; + } +} + +namespace Trinity +{ + +void Assert(char const* file, int line, char const* function, std::string const& debugInfo, char const* message) +{ + std::string formattedMessage = ACORE::StringFormat("\n%s:%i in %s ASSERTION FAILED:\n %s\n", file, line, function, message) + debugInfo + '\n'; + fprintf(stderr, "%s", formattedMessage.c_str()); + fflush(stderr); + Crash(formattedMessage.c_str()); } -void Assert(char const* file, int line, char const* function, char const* message, char const* format, ...) +void Assert(char const* file, int line, char const* function, std::string const& debugInfo, char const* message, char const* format, ...) { va_list args; va_start(args, format); - fprintf(stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s ", file, line, function, message); - vfprintf(stderr, format, args); - fprintf(stderr, "\n"); + std::string formattedMessage = ACORE::StringFormat("\n%s:%i in %s ASSERTION FAILED:\n %s\n", file, line, function, message) + FormatAssertionMessage(format, args) + '\n' + debugInfo + '\n'; + va_end(args); + + fprintf(stderr, "%s", formattedMessage.c_str()); fflush(stderr); - va_end(args); - *((volatile int*)NULL) = 0; - exit(1); + Crash(formattedMessage.c_str()); } void Fatal(char const* file, int line, char const* function, char const* message, ...) @@ -39,22 +84,22 @@ void Fatal(char const* file, int line, char const* function, char const* message va_list args; va_start(args, message); - fprintf(stderr, "\n%s:%i in %s FATAL ERROR:\n ", file, line, function); - vfprintf(stderr, message, args); - fprintf(stderr, "\n"); + std::string formattedMessage = ACORE::StringFormat("\n%s:%i in %s FATAL ERROR:\n", file, line, function) + FormatAssertionMessage(message, args) + '\n'; + va_end(args); + + fprintf(stderr, "%s", formattedMessage.c_str()); fflush(stderr); std::this_thread::sleep_for(std::chrono::seconds(10)); - *((volatile int*)NULL) = 0; - exit(1); + Crash(formattedMessage.c_str()); } void Error(char const* file, int line, char const* function, char const* message) { - fprintf(stderr, "\n%s:%i in %s ERROR:\n %s\n", - file, line, function, message); - *((volatile int*)NULL) = 0; - exit(1); + std::string formattedMessage = ACORE::StringFormat("\n%s:%i in %s ERROR:\n %s\n", file, line, function, message); + fprintf(stderr, "%s", formattedMessage.c_str()); + fflush(stderr); + Crash(formattedMessage.c_str()); } void Warning(char const* file, int line, char const* function, char const* message) @@ -65,18 +110,24 @@ void Warning(char const* file, int line, char const* function, char const* messa void Abort(char const* file, int line, char const* function) { - fprintf(stderr, "\n%s:%i in %s ABORTED.\n", - file, line, function); - *((volatile int*)NULL) = 0; - exit(1); + std::string formattedMessage = ACORE::StringFormat("\n%s:%i in %s ABORTED.\n", file, line, function); + fprintf(stderr, "%s", formattedMessage.c_str()); + fflush(stderr); + Crash(formattedMessage.c_str()); } -void AbortHandler(int /*sigval*/) +void AbortHandler(int sigval) { // nothing useful to log here, no way to pass args - *((volatile int*)NULL) = 0; - exit(1); + std::string formattedMessage = ACORE::StringFormat("Caught signal %i\n", sigval); + fprintf(stderr, "%s", formattedMessage.c_str()); + fflush(stderr); + Crash(formattedMessage.c_str()); } - } // namespace Trinity + +std::string GetDebugInfo() +{ + return ""; +} |
