Age | Commit message (Collapse) | Author |
|
|
|
|
|
|
|
We need LLSingleton machinery to be able to reference get_id() without also
depending on all the rest of LLCoros -- since LLCoros isa LLSingleton.
|
|
Change the module-static thread_specific_ptr to a function-static
thread_specific_ptr so it will be initialized on demand -- since LLSingleton
will need to rely on get_id(). Note that since LLCoros isa LLSingleton, we
must take great care to avoid circularity.
Introduce a private helper class LLCoros::Current to obtain and bind that
thread_specific_ptr. Change all existing internal references from the static
thread_specific_ptr to the new Current helper class.
|
|
Specifically, add DEBUG logging to the code that maintains the stack of
LLSingletons currently being initialized. This involves passing
LLSingletonBase's constructor the name of LLSingleton's template parameter
subclass, since during that constructor typeid(*this).name() will only produce
"LLSingletonBase".
Also add logdebugs() and oktolog() helper functions.
|
|
LLError machinery depends on two different LLSingletons. Its is_available()
function is primarily for LLSingleton itself to determine whether it is, or is
not, safe to log. Until both of LLError's LLSingletons have been constructed,
attempting to log LLSingleton operations could produce infinite recursion.
|
|
LLError::abbreviateFile() is specifically to avoid cluttering log output with
the prefix of an absolute file path on the original build system, pointless
for anyone trying to read the log.
|
|
LLError::abbreviateFile() is specifically to avoid cluttering log output with
the prefix of an absolute file path on the original build system, pointless
for anyone trying to read the log.
|
|
Raw lllog() doesn't work for varying log level, which is why LL_VLOGS()
exists.
|
|
|
|
Raw lllog() doesn't work for varying log level, which is why LL_VLOGS()
exists.
|
|
|
|
In some places we want to log the same information but with different severity
depending on specifics. In other cases we need to test the availability of the
logging subsystem before engaging it. LL_VLOGS() accepts an LLError::ELevel
argument that can differ with each call, while retaining the desirable feature
of deciding only once for each level.
|
|
|
|
|
|
|
|
|
|
|
|
for consistency with everything else, so we can use SUBSYSTEM_CLEANUP() macro
to call it.
|
|
Specifically, log as LLSingleton captures inter-Singleton dependencies. Also
log cleanupAll() calls to cleanupSingleton() and deleteAll() calls to
deleteSingleton(), since they happen in an implicitly-determined order. But do
not log anything during the implicit LLSingletonBase::deleteAll() call
triggered by the runtime destroying the last LLSingleton's static data. That's
too late in the run; even std::cerr might already have been destroyed!
|
|
|
|
Introduce corresponding llcleanup.cpp, llinitdestroyclass.cpp modules to
contain code that performs logging calls.
Track class::method names for LLInitClass<T> and LLDestroyClass<T> subclasses,
and log them when called. The order in which these calls occur could be
relevant to bugs, and could surface the need to convert to LLSingleton
dependencies.
|
|
clang gets nervous about expressions that call functions inside typeid(), even
though these particular typeid() calls are runtime expressions on runtime
values. Extract the offending calls to a previous statement.
|
|
|
|
This particular test relied on there being exactly one instance of the string
"indra" in the source file's __FILE__ path -- which is usually true, but not
if the developer clones the viewer source repo under a parent directory whose
path itself contains "indra". Fix to handle any number of occurrences.
|
|
This means that an exception derived from LLContinueError thrown in an
LLEventPump listener won't prevent other listeners on the same LLEventPump
from receiving that event.
|
|
|
|
|
|
Wrap coroutine call in try/catch in top-level coroutine wrapper function
LLCoros::toplevel(). Distinguish exception classes derived from
LLContinueError (log and continue) from all others (crash with LL_ERRS).
Enhance CRASH_ON_UNHANDLED_EXCEPTIONS() and LOG_UNHANDLED_EXCEPTIONS() macros
to accept a context string to supplement the log message. This lets us replace
many places that called boost::current_exception_diagnostic_information() with
LOG_UNHANDLED_EXCEPTIONS() instead, since the explicit calls were mostly to
log supplemental information.
Provide supplemental information (coroutine name, function parameters) for
some of the previous LOG_UNHANDLED_EXCEPTIONS() calls. This information
duplicates LL_DEBUGS() information at the top of these functions, but in a
typical log file we wouldn't see the LL_DEBUGS() message.
Eliminate a few catch (std::exception e) clauses: the information we get from
boost::current_exception_diagnostic_information() in a catch (...) clause
makes it unnecessary to distinguish.
In a few cases, add a final 'throw;' to a catch (...) clause: having logged
the local context info, propagate the exception to be caught by higher-level
try/catch.
In a couple places, couldn't resist reconciling indentation within a
particular function: tabs where the rest of the function uses tabs, spaces
where the rest of the function uses spaces.
In LLLogin::Impl::loginCoro(), eliminate some confusing comments about an
array of rewritten URIs that date back to a long-deleted implementation.
|
|
since Visual Studio doesn't know __PRETTY_FUNCTION__, and Boost already has a
portable macro to Do The Right Thing.
|
|
Turns out we have a surprising number of catch (...) clauses in the viewer
code base. If all we currently do is
LL_ERRS() << "unknown exception" << LL_ENDL;
then call CRASH_ON_UNHANDLED_EXCEPTION() instead. If what we do is
LL_WARNS() << "unknown exception" << LL_ENDL;
then call LOG_UNHANDLED_EXCEPTION() instead.
Since many places need LOG_UNHANDLED_EXCEPTION() and nobody catches
LLContinueError yet, eliminate LLContinueError& parameter from
LOG_UNHANDLED_EXCEPTION(). This permits us to use the same log message as
CRASH_ON_UNHANDLED_EXCEPTION(), just with a different severity level.
Where a catch (...) clause actually provides contextual information, or makes
an error string, add boost::current_exception_diagnostic_information() to try
to figure out actual exception class and message.
|
|
|
|
A level of preprocessor indirection lets us later change the implementation if
desired.
|
|
llexception_test.cpp is an unusual test source in that it need not be verified
on every build, so its invocation in indra/llcommon/CMakeLists.txt is
commented out with that remark. Its purpose is to help a developer decide what
base class(es) to use for LLException, how to throw and how to catch.
Our current conclusions are written up as comments in llexception_test.cpp.
Added CRASH_ON_UNHANDLED_EXCEPTION() and LOG_UNHANDLED_EXCEPTION() macros to
llexception.h -- macros to log __FILE__, __LINE__ and __PRETTY_FUNCTION__ of
the catch site. These invoke functions in llexception.cpp so we don't need to
#include llerror.h for every possible catch site.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AndreyK regarding script compiles/resets.
|
|
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.
|
|
|
|
|
|
The LLApp API used to consist of init(), mainLoop(), cleanup() methods. This
makes sense -- but on Mac that structure was being subverted. The method
called mainLoop() was in fact being called once per frame. There was
initialization code in the method, which (on Mac) needed to be skipped with an
already-initialized bool. There was a 'while' loop which (on Mac) needed to be
turned into an 'if' instead so the method would return after every frame.
Rename LLApp::mainLoop() to frame(). Propagate through subclasses LLAppViewer
and LLCrashLogger. Document the fact that frame() returns true to mean "done."
(This was always the case, but had to be inferred from the code.)
Rename the Mac Objective-C function mainLoop to oneFrame. Rename the C++ free
function it calls from runMainLoop() to pumpMainLoop(). Add comments to
llappdelegate-objc.mm explaining (inferred) control flow.
Change the Linux viewer main() and the Windows viewer WINMAIN() from a single
LLAppViewer::mainLoop() call to repeatedly call frame() until it returns true.
Move initialization code from the top of LLAppViewer::frame() to the init()
method, where it more properly belongs. Remove corresponding
mMainLoopInitialized flag (and all references) from LLAppViewer.
Remove 'while (! LLApp::isExiting())' (or on Mac, 'if (! LLApp::isExiting())')
from LLAppViewer::frame() -- thus unindenting the whole body of the 'while'
and causing many lines of apparent change. (Apologies to reviewers.)
There are four LLApp states: APP_STATUS_RUNNING, APP_STATUS_QUITTING,
APP_STATUS_STOPPED and APP_STATUS_ERROR. Change LLAppViewer::frame() return
value from (isExiting()) (QUITTING or ERROR) to (! isRunning()). I do not know
under what circumstances the state might transition to STOPPED during a
frame() call, but I'm quite sure that if it does, we don't want to call
frame() again. We only want a subsequent call if the state is RUNNING.
Also rename mainLoop() method in LLCrashLogger subclasses
LLCrashLoggerWindows, LLCrashLoggerMac, LLCrashLoggerLinux. Of course it's
completely up to the frame() method whether to yield control; none of those in
fact do. Honor protocol by returning true (frame() is done), even though each
one's main() caller ignores the return value.
In fact LLCrashLoggerWindows::mainLoop() wasn't using the return protocol
correctly anyway, returning wParam or 0 or 1 -- possibly because the return
protocol was never explicitly documented. It should always return true: "I'm
done, don't call me again."
|