diff options
Diffstat (limited to 'indra/llcommon/llerror.cpp')
-rw-r--r-- | indra/llcommon/llerror.cpp | 128 |
1 files changed, 61 insertions, 67 deletions
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 335a0995fe..d98229fb0a 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -25,6 +25,7 @@ * $/LicenseInfo$ */ +#define _LLERROR_CPP_ #include "linden_common.h" #include "llerror.h" @@ -181,32 +182,35 @@ namespace { return LLError::getEnabledLogTypesMask() & 0x04; } + LL_FORCE_INLINE std::string createANSI(const std::string& color) + { + std::string ansi_code; + ansi_code += '\033'; + ansi_code += "["; + ansi_code += color; + ansi_code += "m"; + return ansi_code; + } + virtual void recordMessage(LLError::ELevel level, const std::string& message) override - { - if (ANSI_PROBE == mUseANSI) - mUseANSI = (checkANSI() ? ANSI_YES : ANSI_NO); + { + static std::string s_ansi_error = createANSI("31"); // red + static std::string s_ansi_warn = createANSI("34"); // blue + static std::string s_ansi_debug = createANSI("35"); // magenta + + mUseANSI = (ANSI_PROBE == mUseANSI) ? (checkANSI() ? ANSI_YES : ANSI_NO) : mUseANSI; if (ANSI_YES == mUseANSI) { - // Default all message levels to bold so we can distinguish our own messages from those dumped by subprocesses and libraries. - colorANSI("1"); // bold - switch (level) { - case LLError::LEVEL_ERROR: - colorANSI("31"); // red - break; - case LLError::LEVEL_WARN: - colorANSI("34"); // blue - break; - case LLError::LEVEL_DEBUG: - colorANSI("35"); // magenta - break; - default: - break; - } + writeANSI((level == LLError::LEVEL_ERROR) ? s_ansi_error : + (level == LLError::LEVEL_WARN) ? s_ansi_warn : + s_ansi_debug, message); } - fprintf(stderr, "%s\n", message.c_str()); - if (ANSI_YES == mUseANSI) colorANSI("0"); // reset + else + { + fprintf(stderr, "%s\n", message.c_str()); + } } private: @@ -217,11 +221,14 @@ namespace { ANSI_NO } mUseANSI; - void colorANSI(const std::string color) + LL_FORCE_INLINE void writeANSI(const std::string& ansi_code, const std::string& message) { - // ANSI color code escape sequence - fprintf(stderr, "\033[%sm", color.c_str() ); - }; + static std::string s_ansi_bold = createANSI("1"); // bold + static std::string s_ansi_reset = createANSI("0"); // reset + // ANSI color code escape sequence, message, and reset in one fprintf call + // Default all message levels to bold so we can distinguish our own messages from those dumped by subprocesses and libraries. + fprintf(stderr, "%s%s%s\n%s", s_ansi_bold.c_str(), ansi_code.c_str(), message.c_str(), s_ansi_reset.c_str() ); + } bool checkANSI(void) { @@ -232,8 +239,8 @@ namespace { return (0 != isatty(2)) && (NULL == getenv("LL_NO_ANSI_COLOR")); #endif // LL_LINUX - return false; - }; + return FALSE; // works in a cygwin shell... ;) + } }; class RecordToFixedBuffer : public LLError::Recorder @@ -482,7 +489,7 @@ namespace LLError LevelMap mTagLevelMap; std::map<std::string, unsigned int> mUniqueLogMessages; - LLError::FatalFunction mCrashFunction; + LLError::FatalHook mFatalHook; LLError::TimeFunction mTimeFunction; Recorders mRecorders; @@ -522,7 +529,7 @@ namespace LLError mFileLevelMap(), mTagLevelMap(), mUniqueLogMessages(), - mCrashFunction(NULL), + mFatalHook(NULL), mTimeFunction(NULL), mRecorders(), mFileRecorder(), @@ -683,7 +690,6 @@ namespace LLError::setDefaultLevel(LLError::LEVEL_INFO); LLError::setAlwaysFlush(true); LLError::setEnabledLogTypesMask(0xFFFFFFFF); - LLError::setFatalFunction(LLError::crashAndLoop); LLError::setTimeFunction(LLError::utcTime); // log_to_stderr is only false in the unit and integration tests to keep builds quieter @@ -719,16 +725,20 @@ namespace LLError commonInit(user_dir, app_dir, log_to_stderr); } - void setFatalFunction(const FatalFunction& f) + void setFatalHook(const FatalHook& fatal_hook) { SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); - s->mCrashFunction = f; - } - - FatalFunction getFatalFunction() + LL_DEBUGS("FatalHook") << "set fatal hook to " << (fatal_hook ? "non-null" : "null") + << " was " << (s->mFatalHook ? "non-null" : "null") + << LL_ENDL; + s->mFatalHook = fatal_hook; + } + + FatalHook getFatalHook() { SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); - return s->mCrashFunction; + LL_DEBUGS("FatalHook") << "read fatal hook was " << (s->mFatalHook ? "non-null" : "null") << LL_ENDL; + return s->mFatalHook; } std::string getFatalMessage() @@ -1306,12 +1316,12 @@ namespace LLError return ; } - void Log::flush(std::ostringstream* out, const CallSite& site) + ErrFatalHookResult Log::flush(std::ostringstream* out, const CallSite& site) { LLMutexTrylock lock(&gLogMutex,5); if (!lock.isLocked()) { - return; + return ERR_DO_NOT_CRASH; // because this wasn't logged, it cannot be fatal } // If we hit a logging request very late during shutdown processing, @@ -1319,7 +1329,7 @@ namespace LLError // DO NOT resurrect them. if (Settings::wasDeleted() || Globals::wasDeleted()) { - return; + return ERR_DO_NOT_CRASH; // because this wasn't logged, it cannot be fatal } Globals* g = Globals::getInstance(); @@ -1353,7 +1363,7 @@ namespace LLError } else { - return; + return ERR_DO_NOT_CRASH; // because this wasn't logged, it cannot be fatal } } else @@ -1369,12 +1379,19 @@ namespace LLError if (site.mLevel == LEVEL_ERROR) { - g->mFatalMessage = message; - if (s->mCrashFunction) - { - s->mCrashFunction(message); - } + if (s->mFatalHook) + { + return s->mFatalHook(message); + } + else + { + return ERR_CRASH; // calling macro should crash + } } + else + { + return ERR_DO_NOT_CRASH; // not ERROR, so do not crash + } } } @@ -1437,29 +1454,6 @@ namespace LLError return s->mShouldLogCallCounter; } -#if LL_WINDOWS - // VC80 was optimizing the error away. - #pragma optimize("", off) -#endif - void crashAndLoop(const std::string& message) - { - // Now, we go kaboom! - int* make_me_crash = NULL; - - *make_me_crash = 0; - - while(true) - { - // Loop forever, in case the crash didn't work? - } - - // this is an attempt to let Coverity and other semantic scanners know that this function won't be returning ever. - exit(EXIT_FAILURE); - } -#if LL_WINDOWS - #pragma optimize("", on) -#endif - std::string utcTime() { time_t now = time(NULL); |