summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2016-08-18 17:33:44 -0400
committerNat Goodspeed <nat@lindenlab.com>2016-08-18 17:33:44 -0400
commit4d10172d8b2c72fa809e322a3b4ff326b19ff340 (patch)
treed9bb8e0e4658201d4ffa03795bf0617c49f94694 /indra/llcommon
parentc7bf8af6378a54c3d03e77b161b7ba3b36186576 (diff)
MAINT-5011: Catch unhandled exceptions in LLCoros coroutines.
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.
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/llcoros.cpp14
-rw-r--r--indra/llcommon/llexception.cpp21
-rw-r--r--indra/llcommon/llexception.h13
3 files changed, 34 insertions, 14 deletions
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index d16bf0160b..4ee8e6d796 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -38,6 +38,7 @@
#include "llevents.h"
#include "llerror.h"
#include "stringize.h"
+#include "llexception.h"
// do nothing, when we need nothing done
void LLCoros::no_cleanup(CoroData*) {}
@@ -235,7 +236,18 @@ void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& calla
// capture the 'self' param in CoroData
data->mSelf = &self;
// run the code the caller actually wants in the coroutine
- callable();
+ try
+ {
+ callable();
+ }
+ catch (const LLContinueError& e)
+ {
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << data->mName));
+ }
+ catch (...)
+ {
+ CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << data->mName));
+ }
// This cleanup isn't perfectly symmetrical with the way we initially set
// data->mPrev, but this is our last chance to reset mCurrentCoro.
sCurrentCoro.reset(data->mPrev);
diff --git a/indra/llcommon/llexception.cpp b/indra/llcommon/llexception.cpp
index 9a6dfee3f1..791b115a8c 100644
--- a/indra/llcommon/llexception.cpp
+++ b/indra/llcommon/llexception.cpp
@@ -24,25 +24,32 @@
namespace {
// used by crash_on_unhandled_exception_() and log_unhandled_exception_()
void log_unhandled_exception_(LLError::ELevel level,
- const char* file, int line, const char* pretty_function)
+ const char* file, int line, const char* pretty_function,
+ const std::string& context)
{
// log same message but allow caller-specified severity level
// lllog() is the macro underlying LL_ERRS(), LL_WARNS() et al.
lllog(level, false) << file << "(" << line << "): Unhandled exception caught in "
- << pretty_function
- << ":\n" << boost::current_exception_diagnostic_information() << LL_ENDL;
+ << pretty_function;
+ if (! context.empty())
+ {
+ LL_CONT << ": " << context;
+ }
+ LL_CONT << ":\n" << boost::current_exception_diagnostic_information() << LL_ENDL;
}
}
-void crash_on_unhandled_exception_(const char* file, int line, const char* pretty_function)
+void crash_on_unhandled_exception_(const char* file, int line, const char* pretty_function,
+ const std::string& context)
{
// LL_ERRS() terminates and propagates message into crash dump.
- log_unhandled_exception_(LLError::LEVEL_ERROR, file, line, pretty_function);
+ log_unhandled_exception_(LLError::LEVEL_ERROR, file, line, pretty_function, context);
}
-void log_unhandled_exception_(const char* file, int line, const char* pretty_function)
+void log_unhandled_exception_(const char* file, int line, const char* pretty_function,
+ const std::string& context)
{
// Use LL_WARNS() because we seriously do not expect this to happen
// routinely, but we DO expect to return from this function.
- log_unhandled_exception_(LLError::LEVEL_WARN, file, line, pretty_function);
+ log_unhandled_exception_(LLError::LEVEL_WARN, file, line, pretty_function, context);
}
diff --git a/indra/llcommon/llexception.h b/indra/llcommon/llexception.h
index 384b2271fb..dfcb7c192f 100644
--- a/indra/llcommon/llexception.h
+++ b/indra/llcommon/llexception.h
@@ -31,6 +31,7 @@
* boost::current_exception_diagnostic_information() is quite wonderful: if
* all we need to do with an exception is log it, in most places we should
* catch (...) and log boost::current_exception_diagnostic_information().
+ * See CRASH_ON_UNHANDLED_EXCEPTION() and LOG_UNHANDLED_EXCEPTION() below.
*
* There may be circumstances in which it would be valuable to distinguish an
* exception explicitly thrown by viewer code from an exception thrown by
@@ -71,14 +72,14 @@ struct LLContinueError: public LLException
#define LLTHROW(x) BOOST_THROW_EXCEPTION(x)
/// Call this macro from a catch (...) clause
-#define CRASH_ON_UNHANDLED_EXCEPTION() \
- crash_on_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION)
-void crash_on_unhandled_exception_(const char*, int, const char*);
+#define CRASH_ON_UNHANDLED_EXCEPTION(CONTEXT) \
+ crash_on_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, CONTEXT)
+void crash_on_unhandled_exception_(const char*, int, const char*, const std::string&);
/// Call this from a catch (const LLContinueError&) clause, or from a catch
/// (...) clause in which you do NOT want the viewer to crash.
-#define LOG_UNHANDLED_EXCEPTION() \
- log_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION)
-void log_unhandled_exception_(const char*, int, const char*);
+#define LOG_UNHANDLED_EXCEPTION(CONTEXT) \
+ log_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, CONTEXT)
+void log_unhandled_exception_(const char*, int, const char*, const std::string&);
#endif /* ! defined(LL_LLEXCEPTION_H) */