summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2021-05-11 21:42:14 -0400
committerNat Goodspeed <nat@lindenlab.com>2021-05-11 21:42:14 -0400
commitc9fc4349b7d4ab1f5a7bfc0125014a96a07e51a3 (patch)
tree33f8251a6f3786d9ea0e1351d08b9840e0322b23 /indra/newview
parent95d8085fa42ca73773a06f2bd5622f69aef0e598 (diff)
SL-10297: Move LL_ERRS crash location into the LL_ERRS macro itself.
Introduce Oz's LLERROR_CRASH macro analogous to the old LLError::crashAndLoop() function. Change LL_ENDL macro so that, after calling flush(), if the CallSite is for LEVEL_ERROR, we invoke LLERROR_CRASH right there. Change the meaning of LLError::FatalFunction. It used to be responsible for the actual crash (hence crashAndLoop()). Now, instead, its role is to disrupt control flow in some other way if you DON'T want to crash: throw an exception, or call exit() or some such. Any FatalFunction that returns normally will fall into the new crash in LL_ENDL. Accordingly, the new default FatalFunction is a no-op lambda. This eliminates the need to test for empty (not set) FatalFunction in Log::flush(). Remove LLError::crashAndLoop() because the official LL_ERRS crash is now in LL_ENDL. One of the two common use cases for setFatalFunction() used to be to intercept control in the last moments before crashing -- not to crash or to avoid crashing, but to capture the LL_ERRS message in some way. Especially when that's temporary, though (e.g. LLLeap), saving and restoring the previous FatalFunction only works when the lifespans of the relevant objects are strictly LIFO. Either way, that's a misuse of FatalFunction. Fortunately the Recorder mechanism exactly addresses that case. Introduce a GenericRecorder template subclass, with LLError::addGenericRecorder(callable) that accepts a callable with suitable (level, message) signature, instantiates a GenericRecorder, adds it to the logging machinery and returns the RecorderPtr for possible later use with removeRecorder(). Change llappviewer.cpp's errorCallback() to an addGenericRecorder() callable. Its role was simply to update gDebugInfo["FatalMessage"] with the LL_ERRS message, then call writeDebugInfo(), before calling crashAndLoop() to finish crashing. Remove the crashAndLoop() call, retaining the gDebugInfo logic. Pass errorCallback() to LLError::addGenericRecorder() instead of setFatalFunction(). Oddly, errorCallback()'s crashAndLoop() call was conditional on a compile-time SHADER_CRASH_NONFATAL symbol. The new mechanism provides no way to support SHADER_CRASH_NONFATAL -- it is a Bad Idea to return normally from any LL_ERRS invocation! Rename LLLeapImpl::fatalFunction() to onError(). Instead of passing it to LLError::setFatalFunction(), pass it to addGenericRecorder(). Capture the returned RecorderPtr in mRecorder, replacing mPrevFatalFunction. Then ~LLLeapImpl() calls removeRecorder(mRecorder) instead of restoring mPrevFatalFunction (which, as noted above, was order-sensitive). Of course, every enabled Recorder is called with every log message. onError() and errorCallback() must specifically test for calls with LEVEL_ERROR. LLSingletonBase::logerrs() used to call LLError::getFatalFunction(), check the return and call it if non-empty, else call LLError::crashAndLoop(). Replace all that with LLERROR_CRASH. Remove from llappviewer.cpp the watchdog_llerrs_callback() and watchdog_killer_callback() functions. watchdog_killer_callback(), passed to Watchdog::init(), used to setFatalFunction(watchdog_llerrs_callback) and then invoke LL_ERRS() -- which seems a bit roundabout. watchdog_llerrs_callback(), in turn, replicated much of the logic in the primary errorCallback() function before replicating the crash from llwatchdog.cpp's default_killer_callback(). Instead, pass LLWatchdog::init() a lambda that invokes the LL_ERRS() message formerly found in watchdog_killer_callback(). It no longer needs to override FatalFunction with watchdog_llerrs_callback() because errorCallback() will still be called as a Recorder, obviating watchdog_llerrs_callback()'s first half; and LL_ENDL will handle the crash, obviating the second half. Remove from llappviewer.cpp the static fast_exit() function, which was simply an alias for _exit() acceptable to boost::bind(). Use a lambda directly calling _exit() instead of using boost::bind() at all. In the CaptureLog class in llcommon/tests/wrapllerrs.h, instead of statically referencing the wouldHaveCrashed() function from test.cpp, simply save and restore the current FatalFunction across the LLError::saveAndResetSettings() call. llerror_test.cpp calls setFatalFunction(fatalCall), where fatalCall() was a function that simply set a fatalWasCalled bool rather than actually crashing in any way. Of course, that implementation would now lead to crashing the test program. Make fatalCall() throw a new FatalWasCalled exception. Introduce a CATCH(LL_ERRS("tag"), "message") macro that expands to: LL_ERRS("tag") << "message" << LL_ENDL; within a try/catch block that catches FatalWasCalled and sets the same bool. Change all existing LL_ERRS() in llerror_test.cpp to corresponding CATCH() calls. In fact there's also an LL_DEBUGS(bad tag) invocation that exercises an LL_ERRS internal to llerror.cpp; wrap that too.
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/llappviewer.cpp67
1 files changed, 17 insertions, 50 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 0b2cdff36c..b03e821d32 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -760,17 +760,6 @@ 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);
-}
-
-
-}
-
bool LLAppViewer::init()
{
@@ -822,9 +811,9 @@ bool LLAppViewer::init()
if (rc >= 0)
{
// QAModeTermCode set, terminate with that rc on LL_ERRS. Use
- // fast_exit() rather than exit() because normal cleanup depends too
+ // _exit() rather than exit() because normal cleanup depends too
// much on successful startup!
- LLError::setFatalFunction(boost::bind(fast_exit, rc));
+ LLError::setFatalFunction([rc](const std::string&){ _exit(rc); });
}
mAlloc.setProfilingEnabled(gSavedSettings.getBOOL("MemProfiling"));
@@ -2185,28 +2174,6 @@ bool LLAppViewer::cleanup()
return true;
}
-// A callback for LL_ERRS() to call during the watchdog error.
-void watchdog_llerrs_callback(const std::string &error_string)
-{
- gLLErrorActivated = true;
-
- gDebugInfo["FatalMessage"] = error_string;
- LLAppViewer::instance()->writeDebugInfo();
-
-#ifdef LL_WINDOWS
- RaiseException(0,0,0,0);
-#else
- raise(SIGQUIT);
-#endif
-}
-
-// A callback for the watchdog to call.
-void watchdog_killer_callback()
-{
- LLError::setFatalFunction(watchdog_llerrs_callback);
- LL_ERRS() << "Watchdog killer event" << LL_ENDL;
-}
-
bool LLAppViewer::initThreads()
{
static const bool enable_threads = true;
@@ -2241,24 +2208,23 @@ bool LLAppViewer::initThreads()
return true;
}
-void errorCallback(const std::string &error_string)
+void errorCallback(LLError::ELevel level, const std::string &error_string)
{
+ if (level == LLError::LEVEL_ERROR)
+ {
#ifndef LL_RELEASE_FOR_DOWNLOAD
- OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK);
+ OSMessageBox(error_string, LLTrans::getString("MBFatalError"), OSMB_OK);
#endif
- //Set the ErrorActivated global so we know to create a marker file
- gLLErrorActivated = true;
-
- gDebugInfo["FatalMessage"] = error_string;
- // We're not already crashing -- we simply *intend* to crash. Since we
- // haven't actually trashed anything yet, we can afford to write the whole
- // static info file.
- LLAppViewer::instance()->writeDebugInfo();
+ //Set the ErrorActivated global so we know to create a marker file
+ gLLErrorActivated = true;
-#ifndef SHADER_CRASH_NONFATAL
- LLError::crashAndLoop(error_string);
-#endif
+ gDebugInfo["FatalMessage"] = error_string;
+ // We're not already crashing -- we simply *intend* to crash. Since we
+ // haven't actually trashed anything yet, we can afford to write the whole
+ // static info file.
+ LLAppViewer::instance()->writeDebugInfo();
+ }
}
void LLAppViewer::initLoggingAndGetLastDuration()
@@ -2269,7 +2235,7 @@ void LLAppViewer::initLoggingAndGetLastDuration()
LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "")
,gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")
);
- LLError::setFatalFunction(errorCallback);
+ LLError::addGenericRecorder(&errorCallback);
//LLError::setTimeFunction(getRuntime);
// Remove the last ".old" log file.
@@ -3030,7 +2996,8 @@ bool LLAppViewer::initWindow()
if (use_watchdog)
{
- LLWatchdog::getInstance()->init(watchdog_killer_callback);
+ LLWatchdog::getInstance()->init(
+ [](){ LL_ERRS() << "Watchdog killer event" << LL_ENDL; });
}
LL_INFOS("AppInit") << "watchdog setting is done." << LL_ENDL;