diff options
Diffstat (limited to 'indra/llcommon/llerror.cpp')
-rw-r--r-- | indra/llcommon/llerror.cpp | 136 |
1 files changed, 85 insertions, 51 deletions
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 64b957b188..06c7aef8ab 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -40,6 +40,7 @@ # include <unistd.h> #endif // !LL_WINDOWS #include <vector> +#include "string.h" #include "llapp.h" #include "llapr.h" @@ -367,7 +368,6 @@ namespace public: std::ostringstream messageStream; bool messageStreamInUse; - std::string mFatalMessage; void addCallSite(LLError::CallSite&); void invalidateCallSites(); @@ -531,21 +531,16 @@ namespace LLError mTags(new const char* [tag_count]), mTagCount(tag_count) { - for (int i = 0; i < tag_count; i++) - { - mTags[i] = tags[i]; - } - switch (mLevel) { - case LEVEL_DEBUG: mLevelString = "DEBUG:"; break; - case LEVEL_INFO: mLevelString = "INFO:"; break; - case LEVEL_WARN: mLevelString = "WARNING:"; break; - case LEVEL_ERROR: mLevelString = "ERROR:"; break; - default: mLevelString = "XXX:"; break; + case LEVEL_DEBUG: mLevelString = "DEBUG"; break; + case LEVEL_INFO: mLevelString = "INFO"; break; + case LEVEL_WARN: mLevelString = "WARNING"; break; + case LEVEL_ERROR: mLevelString = "ERROR"; break; + default: mLevelString = "XXX"; break; }; - mLocationString = llformat("%s(%d) :", abbreviateFile(mFile).c_str(), mLine); + mLocationString = llformat("%s(%d)", abbreviateFile(mFile).c_str(), mLine); #if LL_WINDOWS // DevStudio: __FUNCTION__ already includes the full class name #else @@ -559,13 +554,23 @@ namespace LLError mFunctionString = className(mClassInfo) + "::"; } #endif - mFunctionString += std::string(mFunction) + ":"; - const std::string tag_hash("#"); + mFunctionString += std::string(mFunction); + + for (int i = 0; i < tag_count; i++) + { + if (strchr(tags[i], ' ')) + { + LL_ERRS() << "Space is not allowed in a log tag at " << mLocationString << LL_ENDL; + } + mTags[i] = tags[i]; + } + + mTagString.append("#"); + // always construct a tag sequence; will be just a single # if no tag for (size_t i = 0; i < mTagCount; i++) { - mTagString.append(tag_hash); mTagString.append(mTags[i]); - mTagString.append((i == mTagCount - 1) ? ";" : ","); + mTagString.append("#"); } } @@ -661,16 +666,11 @@ namespace LLError s->mCrashFunction = f; } - FatalFunction getFatalFunction() - { + FatalFunction getFatalFunction() + { SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); - return s->mCrashFunction; - } - - std::string getFatalMessage() - { - return Globals::getInstance()->mFatalMessage; - } + return s->mCrashFunction; + } void setTimeFunction(TimeFunction f) { @@ -905,7 +905,46 @@ namespace LLError namespace { - void writeToRecorders(const LLError::CallSite& site, const std::string& message, bool show_location = true, bool show_time = true, bool show_tags = true, bool show_level = true, bool show_function = true) + void addEscapedMessage(std::ostream& out, const std::string& message) + { + size_t written_out = 0; + size_t all_content = message.length(); + size_t escape_char_index; // always relative to start of message + // Use find_first_of to find the next character in message that needs escaping + for ( escape_char_index = message.find_first_of("\\\n\r"); + escape_char_index != std::string::npos && written_out < all_content; + // record what we've written this iteration, scan for next char that needs escaping + written_out = escape_char_index + 1, escape_char_index = message.find_first_of("\\\n\r", written_out) + ) + { + // found a character that needs escaping, so write up to that with the escape prefix + // note that escape_char_index is relative to the start, not to the written_out offset + out << message.substr(written_out, escape_char_index - written_out) << '\\'; + + // write out the appropriate second character in the escape sequence + char found = message[escape_char_index]; + switch ( found ) + { + case '\\': + out << '\\'; + break; + case '\n': + out << 'n'; + break; + case '\r': + out << 'r'; + break; + } + } + + if ( written_out < all_content ) // if the loop above didn't write everything + { + // write whatever was left + out << message.substr(written_out, std::string::npos); + } + } + + void writeToRecorders(const LLError::CallSite& site, const std::string& escaped_message, bool show_location = true, bool show_time = true, bool show_tags = true, bool show_level = true, bool show_function = true) { LLError::ELevel level = site.mLevel; LLError::SettingsConfigPtr s = LLError::Settings::getInstance()->getSettingsConfig(); @@ -918,32 +957,37 @@ namespace std::ostringstream message_stream; - if (show_time && r->wantsTime() && s->mTimeFunction != NULL) + if (r->wantsTime() && s->mTimeFunction != NULL) { - message_stream << s->mTimeFunction() << " "; + message_stream << s->mTimeFunction(); } - + message_stream << " "; + if (show_level && r->wantsLevel()) { - message_stream << site.mLevelString << " "; + message_stream << site.mLevelString; } + message_stream << " "; - if (show_tags && r->wantsTags()) + if (r->wantsTags()) { message_stream << site.mTagString; } + message_stream << " "; - if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s->mPrintLocation)) + if (r->wantsLocation() || level == LLError::LEVEL_ERROR || s->mPrintLocation) { - message_stream << site.mLocationString << " "; + message_stream << site.mLocationString; } + message_stream << " "; if (show_function && r->wantsFunctionName()) { - message_stream << site.mFunctionString << " "; + message_stream << site.mFunctionString; } + message_stream << " : "; - message_stream << message; + message_stream << escaped_message; r->recordMessage(level, message_stream.str()); } @@ -1186,11 +1230,6 @@ namespace LLError delete out; } - if (site.mLevel == LEVEL_ERROR) - { - writeToRecorders(site, "error", true, true, true, false, false); - } - std::ostringstream message_stream; if (site.mPrintOnce) @@ -1215,19 +1254,14 @@ namespace LLError s->mUniqueLogMessages[message] = 1; } } + + addEscapedMessage(message_stream, message); - message_stream << message; - std::string message_line(message_stream.str()); - - writeToRecorders(site, message_line); - - if (site.mLevel == LEVEL_ERROR) + writeToRecorders(site, message_stream.str()); + + if (site.mLevel == LEVEL_ERROR && s->mCrashFunction) { - g->mFatalMessage = message_line; - if (s->mCrashFunction) - { - s->mCrashFunction(message_line); - } + s->mCrashFunction(message_stream.str()); } } } |