summaryrefslogtreecommitdiff
path: root/indra/llcommon/llerror.cpp
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2020-04-02 13:14:31 -0400
committerNat Goodspeed <nat@lindenlab.com>2020-04-03 10:46:17 -0400
commit962ccb4f01f220850fea35e32c3d92a718d35631 (patch)
tree44e1b62b50c0677754253ab6858f38885b885d48 /indra/llcommon/llerror.cpp
parentdc07509f296661cf7a4d4bceb88a1a897757de98 (diff)
DRTVWR-476: Facilitate debugging test programs with logging.
On Mac, even if you run a test program with --debug or set LOGTEST=DEBUG, it won't log to stderr if you're filtering build output or running the build in an emacs compile buffer. This is because, on Mac, a viewer launched by mouse rather than from the command line is passed a stderr stream that ultimately gets logged to the system Console. The shouldLogToStderr() function is intended to avoid spamming the Console with the (voluminous) viewer log output. It tests whether stderr isatty() and, if not, suppresses calling LLError::logToStderr(). This makes debugging test programs using log output trickier than necessary. Change shouldLogToStderr() to permit logging when either stderr isatty() or is a pipe. The original intention is preserved in that empirically, a viewer launched by mouse is passed a stderr stream identified as a character device rather than as a pipe. Also introduce SetEnv, a class that facilitates setting (e.g.) LOGTEST=DEBUG for specific test programs without setting it for all test programs in the build. Using the constructor for a static object means you can set environment variables before main() is entered, which is important because it's the main() function in test.cpp that acts on the LOGTEST and LOGFAIL environment variables. These changes make it unnecessary to retain the temporary change in test.cpp to force LOGTEST to DEBUG.
Diffstat (limited to 'indra/llcommon/llerror.cpp')
-rw-r--r--indra/llcommon/llerror.cpp43
1 files changed, 30 insertions, 13 deletions
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 1cb93d27f7..0daae96cca 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -39,6 +39,7 @@
#if !LL_WINDOWS
# include <syslog.h>
# include <unistd.h>
+# include <sys/stat.h>
#endif // !LL_WINDOWS
#include <vector>
#include "string.h"
@@ -654,22 +655,38 @@ namespace LLError
namespace
{
- bool shouldLogToStderr()
- {
+ bool shouldLogToStderr()
+ {
#if LL_DARWIN
- // On Mac OS X, stderr from apps launched from the Finder goes to the
- // console log. It's generally considered bad form to spam too much
- // there.
-
- // If stderr is a tty, assume the user launched from the command line or
- // debugger and therefore wants to see stderr. Otherwise, assume we've
- // been launched from the finder and shouldn't spam stderr.
- return isatty(STDERR_FILENO);
+ // On Mac OS X, stderr from apps launched from the Finder goes to the
+ // console log. It's generally considered bad form to spam too much
+ // there. That scenario can be detected by noticing that stderr is a
+ // character device (S_IFCHR).
+
+ // If stderr is a tty or a pipe, assume the user launched from the
+ // command line or debugger and therefore wants to see stderr.
+ if (isatty(STDERR_FILENO))
+ return true;
+ // not a tty, but might still be a pipe -- check
+ struct stat st;
+ if (fstat(STDERR_FILENO, &st) < 0)
+ {
+ // capture errno right away, before engaging any other operations
+ auto errno_save = errno;
+ // this gets called during log-system setup -- can't log yet!
+ std::cerr << "shouldLogToStderr: fstat(" << STDERR_FILENO << ") failed, errno "
+ << errno_save << std::endl;
+ // if we can't tell, err on the safe side and don't write stderr
+ return false;
+ }
+
+ // fstat() worked: return true only if stderr is a pipe
+ return ((st.st_mode & S_IFMT) == S_IFIFO);
#else
- return true;
+ return true;
#endif
- }
-
+ }
+
bool stderrLogWantsTime()
{
#if LL_WINDOWS