summaryrefslogtreecommitdiff
path: root/indra/llcommon/llerror.cpp
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2019-10-28 14:33:36 -0400
committerNat Goodspeed <nat@lindenlab.com>2020-03-25 19:05:17 -0400
commit7845f73c7691d338ef92d653be12337215ff0f49 (patch)
treebc1c37412b188daa995b72eab588bf67f67bb276 /indra/llcommon/llerror.cpp
parent9f446be76ee804bcd2f6ff8546612c9fcaf2a73e (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/llcommon/llerror.cpp')
-rw-r--r--indra/llcommon/llerror.cpp68
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: