summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2015-06-25 16:04:01 -0400
committerNat Goodspeed <nat@lindenlab.com>2015-06-25 16:04:01 -0400
commit0ea1b2a164e0d985c80c8a1afea4b31670efc907 (patch)
treea3f96265f90f7815909135760ca87fcc2d2b96ed
parentd792baf9f7220a374788b35789335a7ae2e62369 (diff)
MAINT-5232: Try to avoid circularity between LLError and LLSingleton.
Part of LLError's logging infrastructure is implemented with an LLSingleton. Therefore, attempts to log from within LLSingleton machinery could potentially go south if LLError's LLSingleton is not yet initialized. Introduce LLError::is_available() in llerrorcontrol.h and llerror.cpp. Make LLSingletonBase::logwarns() and logerrs() consult LLError::is_available() before attempting to use LL_WARNS or LL_ERRS, respectively. Moreover, make all LLSingleton internal logging use logwarns() and logerrs() instead of directly engaging LL_ERRS or LL_WARNS.
-rwxr-xr-xindra/llcommon/llerror.cpp5
-rwxr-xr-xindra/llcommon/llerrorcontrol.h5
-rwxr-xr-xindra/llcommon/llsingleton.cpp64
-rwxr-xr-xindra/llcommon/llsingleton.h6
4 files changed, 58 insertions, 22 deletions
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 2100989316..54524bbe8e 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -402,6 +402,11 @@ namespace
namespace LLError
{
+ bool is_available()
+ {
+ return Globals::instanceExists();
+ }
+
class SettingsConfig : public LLRefCount
{
friend class Settings;
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index 56ac52e5de..56e84f7172 100755
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -189,6 +189,11 @@ namespace LLError
LL_COMMON_API std::string abbreviateFile(const std::string& filePath);
LL_COMMON_API int shouldLogCallCount();
+
+ // Check whether Globals exists. This should only be used by LLSingleton
+ // infrastructure to avoid trying to log when our internal LLSingleton is
+ // unavailable -- circularity ensues.
+ LL_COMMON_API bool is_available();
};
#endif // LL_LLERRORCONTROL_H
diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp
index 204c0d24d0..a3edf925ad 100755
--- a/indra/llcommon/llsingleton.cpp
+++ b/indra/llcommon/llsingleton.cpp
@@ -28,9 +28,11 @@
#include "llsingleton.h"
#include "llerror.h"
+#include "llerrorcontrol.h" // LLError::is_available()
#include "lldependencies.h"
#include <boost/foreach.hpp>
#include <algorithm>
+#include <iostream> // std::cerr in dire emergency
#include <sstream>
#include <stdexcept>
@@ -108,14 +110,14 @@ void LLSingletonBase::pop_initializing()
list_t& list(get_initializing());
if (list.empty())
{
- LL_ERRS() << "Underflow in stack of currently-initializing LLSingletons at "
- << typeid(*this).name() << "::getInstance()" << LL_ENDL;
+ logerrs("Underflow in stack of currently-initializing LLSingletons at ",
+ typeid(*this).name(), "::getInstance()");
}
if (list.back() != this)
{
- LL_ERRS() << "Push/pop mismatch in stack of currently-initializing LLSingletons: "
- << typeid(*this).name() << "::getInstance() trying to pop "
- << typeid(*list.back()).name() << LL_ENDL;
+ logerrs("Push/pop mismatch in stack of currently-initializing LLSingletons: ",
+ typeid(*this).name(), "::getInstance() trying to pop ",
+ typeid(*list.back()).name());
}
// Here we're sure that list.back() == this. Whew, pop it.
list.pop_back();
@@ -151,8 +153,8 @@ void LLSingletonBase::capture_dependency()
// DEBUGGING: Initially, make this crump. We want to know how bad
// the problem is before we add it to the long, sad list of
// ominous warnings that everyone always ignores.
- LL_ERRS() << "LLSingleton circularity: " << out.str()
- << typeid(*this).name() << LL_ENDL;
+ logerrs("LLSingleton circularity: ", out.str().c_str(),
+ typeid(*this).name());
}
else
{
@@ -223,13 +225,13 @@ void LLSingletonBase::cleanupAll()
}
catch (const std::exception& e)
{
- LL_WARNS() << "Exception in " << typeid(*sp).name()
- << "::cleanupSingleton(): " << e.what() << LL_ENDL;
+ logwarns("Exception in ", typeid(*sp).name(),
+ "::cleanupSingleton(): ", e.what());
}
catch (...)
{
- LL_WARNS() << "Unknown exception in " << typeid(*sp).name()
- << "::cleanupSingleton()" << LL_ENDL;
+ logwarns("Unknown exception in ", typeid(*sp).name(),
+ "::cleanupSingleton()");
}
}
}
@@ -250,7 +252,7 @@ void LLSingletonBase::deleteAll()
if (! sp->mDeleteSingleton)
{
// This Should Not Happen... but carry on.
- LL_WARNS() << name << "::mDeleteSingleton not initialized!" << LL_ENDL;
+ logwarns(name, "::mDeleteSingleton not initialized!");
}
else
{
@@ -261,13 +263,11 @@ void LLSingletonBase::deleteAll()
}
catch (const std::exception& e)
{
- LL_WARNS() << "Exception in " << name
- << "::deleteSingleton(): " << e.what() << LL_ENDL;
+ logwarns("Exception in ", name, "::deleteSingleton(): ", e.what());
}
catch (...)
{
- LL_WARNS() << "Unknown exception in " << name
- << "::deleteSingleton()" << LL_ENDL;
+ logwarns("Unknown exception in ", name, "::deleteSingleton()");
}
}
}
@@ -307,13 +307,37 @@ void intrusive_ptr_release(LLSingletonBase::MasterRefcount* mrc)
/*---------------------------- Logging helpers -----------------------------*/
//static
-void LLSingletonBase::logerrs(const char* p1, const char* p2, const char* p3)
+void LLSingletonBase::logerrs(const char* p1, const char* p2, const char* p3, const char* p4)
{
- LL_ERRS() << p1 << p2 << p3 << LL_ENDL;
+ // Check LLError::is_available() because some of LLError's infrastructure
+ // is itself an LLSingleton. If that LLSingleton has not yet been
+ // initialized, trying to log will engage LLSingleton machinery... and
+ // around and around we go.
+ if (LLError::is_available())
+ {
+ LL_ERRS() << p1 << p2 << p3 << p4 << LL_ENDL;
+ }
+ else
+ {
+ // Caller may be a test program, or something else whose stderr is
+ // visible to the user.
+ std::cerr << p1 << p2 << p3 << p4 << std::endl;
+ // The other important side effect of LL_ERRS() is
+ // https://www.youtube.com/watch?v=OMG7paGJqhQ (emphasis on OMG)
+ LLError::crashAndLoop(std::string());
+ }
}
//static
-void LLSingletonBase::logwarns(const char* p1, const char* p2, const char* p3)
+void LLSingletonBase::logwarns(const char* p1, const char* p2, const char* p3, const char* p4)
{
- LL_WARNS() << p1 << p2 << p3 << LL_ENDL;
+ // See logerrs() remarks about is_available().
+ if (LLError::is_available())
+ {
+ LL_WARNS() << p1 << p2 << p3 << p4 << LL_ENDL;
+ }
+ else
+ {
+ std::cerr << p1 << p2 << p3 << p4 << std::endl;
+ }
}
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 7706ed53f2..d66ea33c0c 100755
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -90,9 +90,11 @@ protected:
void capture_dependency();
// delegate LL_ERRS() logging to llsingleton.cpp
- static void logerrs(const char* p1, const char* p2="", const char* p3="");
+ static void logerrs(const char* p1, const char* p2="",
+ const char* p3="", const char* p4="");
// delegate LL_WARNS() logging to llsingleton.cpp
- static void logwarns(const char* p1, const char* p2="", const char* p3="");
+ static void logwarns(const char* p1, const char* p2="",
+ const char* p3="", const char* p4="");
// obtain canonical ref_ptr_t
static ref_ptr_t get_master_refcount();