fix error message reporting?
parent
e409c0492f
commit
e86c0b3d0f
|
|
@ -719,7 +719,7 @@ namespace LLError
|
|||
commonInit(user_dir, app_dir, log_to_stderr);
|
||||
}
|
||||
|
||||
void overrideCrashOnError(const FatalFunction& fatal_function)
|
||||
void setFatalHandler(const FatalFunction& fatal_function)
|
||||
{
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
s->mCrashFunction = fatal_function;
|
||||
|
|
@ -1306,12 +1306,12 @@ namespace LLError
|
|||
return ;
|
||||
}
|
||||
|
||||
bool Log::flush(std::ostringstream* out, const CallSite& site)
|
||||
ErrCrashHandlerResult Log::flush(std::ostringstream* out, const CallSite& site)
|
||||
{
|
||||
LLMutexTrylock lock(&gLogMutex,5);
|
||||
if (!lock.isLocked())
|
||||
{
|
||||
return false; // because this wasn't logged, it cannot be fatal
|
||||
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 +1319,7 @@ namespace LLError
|
|||
// DO NOT resurrect them.
|
||||
if (Settings::wasDeleted() || Globals::wasDeleted())
|
||||
{
|
||||
return false; // because this wasn't logged, it cannot be fatal
|
||||
return ERR_DO_NOT_CRASH; // because this wasn't logged, it cannot be fatal
|
||||
}
|
||||
|
||||
Globals* g = Globals::getInstance();
|
||||
|
|
@ -1353,7 +1353,7 @@ namespace LLError
|
|||
}
|
||||
else
|
||||
{
|
||||
return false; // because this wasn't logged, it cannot be fatal
|
||||
return ERR_DO_NOT_CRASH; // because this wasn't logged, it cannot be fatal
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -1369,20 +1369,18 @@ namespace LLError
|
|||
|
||||
if (site.mLevel == LEVEL_ERROR)
|
||||
{
|
||||
g->mFatalMessage = message;
|
||||
if (s->mCrashFunction)
|
||||
{
|
||||
s->mCrashFunction(message);
|
||||
return false; // because an override is in effect
|
||||
return s->mCrashFunction(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
return true; // calling macro should crash
|
||||
return ERR_CRASH; // calling macro should crash
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false; // not ERROR, so do not crash
|
||||
return ERR_DO_NOT_CRASH; // not ERROR, so do not crash
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -194,6 +194,8 @@ namespace LLError
|
|||
|
||||
struct CallSite;
|
||||
|
||||
enum ErrCrashHandlerResult { ERR_DO_NOT_CRASH, ERR_CRASH };
|
||||
|
||||
class LL_COMMON_API Log
|
||||
{
|
||||
public:
|
||||
|
|
@ -203,7 +205,7 @@ namespace LLError
|
|||
static void flush(std::ostringstream* out, char* message);
|
||||
|
||||
// returns false iff the calling macro should crash
|
||||
static bool flush(std::ostringstream*, const CallSite&);
|
||||
static ErrCrashHandlerResult flush(std::ostringstream*, const CallSite&);
|
||||
|
||||
static std::string demangle(const char* mangled);
|
||||
};
|
||||
|
|
@ -386,7 +388,7 @@ volatile extern int* gCauseCrash;
|
|||
|
||||
#define LL_ENDL \
|
||||
LLError::End(); \
|
||||
if (LLError::Log::flush(_out, _site)) \
|
||||
if (LLError::ERR_CRASH == LLError::Log::flush(_out, _site)) \
|
||||
LLERROR_CRASH \
|
||||
} \
|
||||
} while(0)
|
||||
|
|
|
|||
|
|
@ -93,16 +93,21 @@ namespace LLError
|
|||
Control functions.
|
||||
*/
|
||||
|
||||
typedef boost::function<void(const std::string&)> FatalFunction;
|
||||
// A FatalFunction is called if set using setFatalHandler; its return controls
|
||||
// whether or not the calling error logging code should crash.
|
||||
// ERR_DO_NOT_CRASH should be used only in test code.
|
||||
typedef boost::function<LLError::ErrCrashHandlerResult(const std::string&)> FatalFunction;
|
||||
|
||||
|
||||
/// Override the default behavior of crashing on LL_ERRS; this should NEVER be used except in test code
|
||||
LL_COMMON_API void overrideCrashOnError(const FatalFunction&);
|
||||
LL_COMMON_API void setFatalHandler(const FatalFunction&);
|
||||
// The fatal function will be called when an message of LEVEL_ERROR
|
||||
// is logged. Note: supressing a LEVEL_ERROR message from being logged
|
||||
// (by, for example, setting a class level to LEVEL_NONE), will keep
|
||||
// the that message from causing the fatal funciton to be invoked.
|
||||
// The
|
||||
|
||||
/// Undo the effect of the overrideCrashOnError above
|
||||
/// Undo the effect of the setFatalHandler above
|
||||
LL_COMMON_API void restoreCrashOnError();
|
||||
|
||||
LL_COMMON_API std::string getFatalMessage();
|
||||
|
|
|
|||
|
|
@ -70,7 +70,11 @@ namespace
|
|||
namespace
|
||||
{
|
||||
static bool fatalWasCalled;
|
||||
void fatalCall(const std::string&) { fatalWasCalled = true; }
|
||||
LLError::ErrCrashHandlerResult fatalCall(const std::string&)
|
||||
{
|
||||
fatalWasCalled = true;
|
||||
return LLError::ERR_DO_NOT_CRASH;
|
||||
}
|
||||
}
|
||||
|
||||
namespace tut
|
||||
|
|
@ -120,7 +124,7 @@ namespace tut
|
|||
|
||||
mPriorErrorSettings = LLError::saveAndResetSettings();
|
||||
LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
|
||||
LLError::overrideCrashOnError(fatalCall);
|
||||
LLError::setFatalHandler(fatalCall);
|
||||
LLError::addRecorder(mRecorder);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
|
||||
// statically reference the function in test.cpp... it's short, we could
|
||||
// replicate, but better to reuse
|
||||
extern void wouldHaveCrashed(const std::string& message);
|
||||
extern LLError::ErrCrashHandlerResult wouldHaveCrashed(const std::string& message);
|
||||
|
||||
struct WrapLLErrs
|
||||
{
|
||||
|
|
@ -57,7 +57,7 @@ struct WrapLLErrs
|
|||
:mPriorErrorSettings(LLError::saveAndResetSettings())
|
||||
{
|
||||
// Make LL_ERRS call our own operator() method
|
||||
LLError::overrideCrashOnError(boost::bind(&WrapLLErrs::operator(), this, _1));
|
||||
LLError::setFatalHandler(boost::bind(&WrapLLErrs::operator(), this, _1));
|
||||
}
|
||||
|
||||
~WrapLLErrs()
|
||||
|
|
@ -71,7 +71,7 @@ struct WrapLLErrs
|
|||
FatalException(const std::string& what): LLException(what) {}
|
||||
};
|
||||
|
||||
void operator()(const std::string& message)
|
||||
LLError::ErrCrashHandlerResult operator()(const std::string& message)
|
||||
{
|
||||
// Save message for later in case consumer wants to sense the result directly
|
||||
error = message;
|
||||
|
|
@ -201,7 +201,7 @@ public:
|
|||
mOldSettings(LLError::saveAndResetSettings()),
|
||||
mRecorder(new CaptureLogRecorder())
|
||||
{
|
||||
LLError::overrideCrashOnError(wouldHaveCrashed);
|
||||
LLError::setFatalHandler(wouldHaveCrashed);
|
||||
LLError::setDefaultLevel(level);
|
||||
LLError::addRecorder(mRecorder);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -751,16 +751,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
namespace {
|
||||
// With Xcode 6, _exit() is too magical to use with boost::bind(), so provide
|
||||
// this little helper function.
|
||||
void fast_exit(int rc)
|
||||
{
|
||||
_exit(rc);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
static S32 sQAModeTermCode = 0; // set from QAModeTermCode to specify exit code for LL_ERRS
|
||||
|
||||
bool LLAppViewer::init()
|
||||
{
|
||||
|
|
@ -800,17 +791,8 @@ bool LLAppViewer::init()
|
|||
initMaxHeapSize() ;
|
||||
LLCoros::instance().setStackSize(gSavedSettings.getS32("CoroutineStackSize"));
|
||||
|
||||
// Although initLoggingAndGetLastDuration() is the right place to mess with
|
||||
// overrideCrashOnError(), we can't query gSavedSettings until after
|
||||
// initConfiguration().
|
||||
S32 rc(gSavedSettings.getS32("QAModeTermCode"));
|
||||
if (rc >= 0)
|
||||
{
|
||||
// QAModeTermCode set, terminate with that rc on LL_ERRS. Use
|
||||
// fast_exit() rather than exit() because normal cleanup depends too
|
||||
// much on successful startup!
|
||||
LLError::overrideCrashOnError(boost::bind(fast_exit, rc));
|
||||
}
|
||||
// if a return code is set for error exit, save it here for use in fatalErrorHandler
|
||||
sQAModeTermCode = gSavedSettings.getS32("QAModeTermCode");
|
||||
|
||||
mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling"));
|
||||
|
||||
|
|
@ -2152,8 +2134,7 @@ bool LLAppViewer::initThreads()
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifndef LL_BUGSPLAT
|
||||
void errorCallback(const std::string &error_string)
|
||||
LLError::ErrCrashHandlerResult fatalErrorHandler(const std::string &error_string)
|
||||
{
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK);
|
||||
|
|
@ -2167,8 +2148,15 @@ void errorCallback(const std::string &error_string)
|
|||
// haven't actually trashed anything yet, we can afford to write the whole
|
||||
// static info file.
|
||||
LLAppViewer::instance()->writeDebugInfo();
|
||||
|
||||
if (sQAModeTermCode)
|
||||
{
|
||||
_exit(sQAModeTermCode);
|
||||
return LLError::ERR_DO_NOT_CRASH; // notreached
|
||||
}
|
||||
|
||||
return LLError::ERR_CRASH;
|
||||
}
|
||||
#endif // ! LL_BUGSPLAT
|
||||
|
||||
void LLAppViewer::initLoggingAndGetLastDuration()
|
||||
{
|
||||
|
|
@ -2178,6 +2166,7 @@ void LLAppViewer::initLoggingAndGetLastDuration()
|
|||
LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "")
|
||||
,gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")
|
||||
);
|
||||
LLError::setFatalHandler(fatalErrorHandler);
|
||||
|
||||
// Remove the last ".old" log file.
|
||||
std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
|
||||
|
|
@ -3728,12 +3717,8 @@ void LLAppViewer::processMarkerFiles()
|
|||
else if (marker_is_same_version)
|
||||
{
|
||||
// the file existed, is ours, and matched our version, so we can report on what it says
|
||||
LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec FROZE" << LL_ENDL;
|
||||
# if LL_BUGSPLAT
|
||||
LL_INFOS("MarkerFile") << "Exec marker '"<< mMarkerFileName << "' found; last exec crashed" << LL_ENDL;
|
||||
gLastExecEvent = LAST_EXEC_OTHER_CRASH;
|
||||
# else
|
||||
gLastExecEvent = LAST_EXEC_FROZE;
|
||||
# endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -188,17 +188,17 @@ CrashMetadataSingleton::CrashMetadataSingleton()
|
|||
LLSD info;
|
||||
if (! static_file.is_open())
|
||||
{
|
||||
LL_INFOS() << "Can't open '" << staticDebugPathname
|
||||
LL_WARNS() << "Can't open '" << staticDebugPathname
|
||||
<< "'; no metadata about previous run" << LL_ENDL;
|
||||
}
|
||||
else if (! LLSDSerialize::deserialize(info, static_file, LLSDSerialize::SIZE_UNLIMITED))
|
||||
{
|
||||
LL_INFOS() << "Can't parse '" << staticDebugPathname
|
||||
LL_WARNS() << "Can't parse '" << staticDebugPathname
|
||||
<< "'; no metadata about previous run" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "Metadata from '" << staticDebugPathname << "':" << LL_ENDL;
|
||||
LL_INFOS() << "Previous run metadata from '" << staticDebugPathname << "':" << LL_ENDL;
|
||||
logFilePathname = get_metadata(info, "SLLog");
|
||||
userSettingsPathname = get_metadata(info, "SettingsFilename");
|
||||
OSInfo = get_metadata(info, "OSInfo");
|
||||
|
|
|
|||
|
|
@ -75,9 +75,10 @@
|
|||
|
||||
#include <fstream>
|
||||
|
||||
void wouldHaveCrashed(const std::string& message)
|
||||
LLError::ErrCrashHandlerResult wouldHaveCrashed(const std::string& message)
|
||||
{
|
||||
tut::fail("fatal error message: " + message);
|
||||
return LLError::ERR_DO_NOT_CRASH;
|
||||
}
|
||||
|
||||
namespace tut
|
||||
|
|
@ -149,7 +150,7 @@ public:
|
|||
mOldSettings(LLError::saveAndResetSettings()),
|
||||
mRecorder(new RecordToTempFile(pool))
|
||||
{
|
||||
LLError::overrideCrashOnError(wouldHaveCrashed);
|
||||
LLError::setFatalHandler(wouldHaveCrashed);
|
||||
LLError::setDefaultLevel(level);
|
||||
LLError::addRecorder(mRecorder);
|
||||
}
|
||||
|
|
@ -530,7 +531,7 @@ int main(int argc, char **argv)
|
|||
LLError::initForApplication(".", ".", false /* do not log to stderr */);
|
||||
LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
|
||||
}
|
||||
LLError::overrideCrashOnError(wouldHaveCrashed);
|
||||
LLError::setFatalHandler(wouldHaveCrashed);
|
||||
std::string test_app_name(argv[0]);
|
||||
std::string test_log = test_app_name + ".log";
|
||||
LLFile::remove(test_log);
|
||||
|
|
|
|||
Loading…
Reference in New Issue