diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2019-10-28 14:33:36 -0400 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2020-03-25 19:05:17 -0400 |
commit | 7845f73c7691d338ef92d653be12337215ff0f49 (patch) | |
tree | bc1c37412b188daa995b72eab588bf67f67bb276 /indra | |
parent | 9f446be76ee804bcd2f6ff8546612c9fcaf2a73e (diff) |
DRTVWR-476: Try to log stderr output from classic-C libraries.
Some of the libraries we use produce log output to stderr. Such output can be
informative, but is invisible unless you launch the viewer from a console. In
particular, it's invisible to anyone trying to diagnose a problem by reading
someone else's SecondLife.log file.
Make RecordToFile -- the Recorder subclass engaged by LLError::logToFile() --
redirect STDERR_FILENO to the newly-opened log file so that any subsequent
writes to stderr (or cerr, for that matter) will be captured in the log file.
But first duplicate the original stderr file handle, and restore it when
RecordToFile is destroyed. That way, output written to stderr during the final
moments of application shutdown should still appear on (console) stderr.
Diffstat (limited to 'indra')
-rw-r--r-- | indra/llcommon/llerror.cpp | 68 |
1 files changed, 38 insertions, 30 deletions
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index acd863a316..6ef0fde886 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -119,59 +119,67 @@ namespace { { public: RecordToFile(const std::string& filename): - mName(filename) + mName(filename), + mFile(LLFile::fopen(filename, "a")) { - mFile.open(filename.c_str(), std::ios_base::out | std::ios_base::app); if (!mFile) { - LL_INFOS() << "Error setting log file to " << filename << LL_ENDL; + LL_WARNS() << "Error setting log file to " << filename << LL_ENDL; } else { - if (!LLError::getAlwaysFlush()) - { - mFile.sync_with_stdio(false); - } +#if LL_DARWIN || LL_LINUX + // We use a number of classic-C libraries, some of which write + // log output to stderr. The trouble with that is that unless + // you launch the viewer from a console, stderr output is + // lost. Redirect STDERR_FILENO to write into this log file. + // But first, save the original stream in case we want it later. + mSavedStderr = ::dup(STDERR_FILENO); + ::dup2(::fileno(mFile), STDERR_FILENO); +#endif } } ~RecordToFile() { +#if LL_DARWIN || LL_LINUX + // restore stderr to its original fileno so any subsequent output + // to stderr goes to original stream + ::dup2(mSavedStderr, STDERR_FILENO); +#endif mFile.close(); } - virtual bool enabled() override - { + virtual bool enabled() override + { #ifdef LL_RELEASE_FOR_DOWNLOAD - return 1; + return 1; #else - return LLError::getEnabledLogTypesMask() & 0x02; + return LLError::getEnabledLogTypesMask() & 0x02; #endif - } - - bool okay() const { return mFile.good(); } + } - std::string getFilename() const { return mName; } + bool okay() const { return bool(mFile); } - virtual void recordMessage(LLError::ELevel level, - const std::string& message) override - { - if (LLError::getAlwaysFlush()) - { - mFile << message << std::endl; - } - else - { - mFile << message << "\n"; - } - } + std::string getFilename() const { return mName; } + + virtual void recordMessage(LLError::ELevel level, + const std::string& message) override + { + fwrite(message.c_str(), sizeof(char), message.length(), mFile); + if (LLError::getAlwaysFlush()) + { + ::fflush(mFile); + } + } private: const std::string mName; - llofstream mFile; + LLUniqueFile mFile; + int mSavedStderr{0}; }; - - + + class RecordToStderr : public LLError::Recorder { public: |