Commit Graph

19 Commits (bdc94eac5cda3dd6700a1cd462178b7ac3c4cfec)

Author SHA1 Message Date
Nat Goodspeed c9fc4349b7 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.
2021-05-11 21:42:14 -04:00
Nat Goodspeed f0fa4f94a5 DRTVWR-493: Make catch_llerrs() a member of WrapLLErrs. 2019-08-12 08:26:51 -04:00
Nat Goodspeed adb3f447b3 DRTVWR-493: Introduce test catch_what(), catch_llerrs() functions.
Use them in place of awkward try/catch test boilerplate.
2019-08-10 20:33:59 -04:00
Nat Goodspeed c09d9c12e7 SL-821: Add WSTRINGIZE() and DEWSTRINGIZE() macros for wide strings.
Streamline convenience overload stringize(std::wstring); make convenience
overload wstringize(std::string) symmetrically convert from UTF-8 string.

Also eliminate STRINGIZE() et al. dependency on Boost.Phoenix: use lambdas
instead.

Using lambdas instead of template expansion necessitates reordering some code
in wrapllerrs.h.
2018-05-17 05:45:36 -04:00
Nat Goodspeed 5e9d2f57c8 MAINT-5011: Use LLTHROW() instead of plain BOOST_THROW_EXCEPTION().
A level of preprocessor indirection lets us later change the implementation if
desired.
2016-08-17 11:36:24 -04:00
Nat Goodspeed 9c49a6c91d MAINT-5011: Introduce LLException base class for viewer exceptions.
This also introduces LLContinueError for exceptions which should interrupt
some part of viewer processing (e.g. the current coroutine) but should attempt
to let the viewer session proceed.

Derive all existing viewer exception classes from LLException rather than from
std::runtime_error or std::logic_error.

Use BOOST_THROW_EXCEPTION() rather than plain 'throw' to enrich the thrown
exception with source file, line number and containing function.
2016-07-19 16:25:25 -04:00
Oz Linden c8726aba30 remove execute permission from many files that should not have it 2015-11-10 09:48:56 -05:00
Stinson Linden 08e83a341e MAINT-4009: Final pass refactoring to eliminate memory allocation related to error reporting that is not properly cleaned up. 2014-05-17 00:41:36 +01:00
Stinson Linden 34b2f2d1f8 MAINT-4009: First pass refactoring to eliminate memory related to error reporting that is not properly cleaned up. 2014-05-16 22:44:25 +01:00
Richard Linden 4170ef8ecc fixed llinstancetracker unit test 2013-10-18 09:50:26 -07:00
Graham Madarasz bf6182daa8 Update Mac and Windows breakpad builds to latest 2013-03-29 07:50:08 -07:00
Nat Goodspeed eb1bea2223 IQA-463: LLError::addRecorder() claims ownership of passed Recorder*.
That is, when the underlying LLError::Settings object is destroyed -- possibly
at termination, possibly on LLError::restoreSettings() -- the passed Recorder*
is deleted.
There was much existing code that seemed as unaware of this alarming fact as I
was myself. Passing to addRecorder() a pointer to a stack object, or to a
member of some other object, is just Bad. It might be preferable to make
addRecorder() accept std::auto_ptr<Recorder> to make the ownership transfer
more explicit -- or even boost::shared_ptr<Recorder> instead, which would
allow the caller to either forget or retain the passed Recorder.
This preliminary pass retains the Recorder* dumb pointer API, but documents
the ownership issue, and eliminates known instances of passing pointers to
anything but a standalone heap Recorder subclass object.
2012-04-23 11:26:18 -04:00
Nat Goodspeed b3b51f012f Move std::ostream << CaptureLog logic into CaptureLog::streamto().
That lets us reliably declare the operator<<() free function inline, which
permits multiple translation units in the same executable to #include
"wrapllerrs.h".
2012-03-05 13:03:23 -05:00
Nat Goodspeed cfe37cbfb5 Break out std::ostream << CaptureLog routine for general use. 2012-03-01 22:45:16 -05:00
Nat Goodspeed f0612f6fc4 Allow CaptureLog's consumer to specify desired log level.
Of course, given the way the log machinery works, it's really "everything at
that level or stronger."
2012-03-01 17:30:50 -05:00
Nat Goodspeed f904867720 Make CaptureLog::withMessage() raise tut::failure if not found.
All known callers were using ensure(! withMessage(...).empty()). Centralize
that logic. Make failure message report the string being sought and the log
messages in which it wasn't found.
In case someone does want to permit the search to fail, add an optional
'required' parameter, default true.
Leverage new functionality in llprocess_test.cpp.
2012-03-01 14:33:23 -05:00
Nat Goodspeed 2596816f31 Break out TestRecorder class as CaptureLog into wrapllerrs.h.
Giving more unit tests the ability to capture and examine log output is
generally useful. Renaming the class just makes it less ambiguous: what's a
TestRecorder? Something that records tests?
2012-03-01 13:43:52 -05:00
Oz Linden 06b0d72efa Change license from GPL to LGPL (version 2.1) 2010-08-13 07:24:57 -04:00
Nat Goodspeed dc93462991 svn merge -r113003:119136 svn+ssh://svn.lindenlab.com/svn/linden/branches/login-api/login-api-2 svn+ssh://svn.lindenlab.com/svn/linden/branches/login-api/login-api-3 2009-05-11 20:05:46 +00:00