Skip to content
Snippets Groups Projects
Commit 4617e07b authored by AndreyL ProductEngine's avatar AndreyL ProductEngine
Browse files

Merged in lindenlab/viewer-release

parents 5dd97bc2 086c1342
No related branches found
No related tags found
No related merge requests found
Showing
with 294 additions and 66 deletions
...@@ -519,3 +519,4 @@ e9d350764dfbf5a46229e627547ef5c1b1eeef00 4.0.2-release ...@@ -519,3 +519,4 @@ e9d350764dfbf5a46229e627547ef5c1b1eeef00 4.0.2-release
4070611edd95eb3a683d1cd97c4c07fe67793812 4.0.6-release 4070611edd95eb3a683d1cd97c4c07fe67793812 4.0.6-release
33981d8130f031597b4c7f4c981b18359afb61a0 4.0.7-release 33981d8130f031597b4c7f4c981b18359afb61a0 4.0.7-release
45eaee56883df7a439ed3300c44d3126f7e3a41e 4.0.8-release 45eaee56883df7a439ed3300c44d3126f7e3a41e 4.0.8-release
b280a1c797a3891e68dbc237e73de9cf19f426e9 4.1.1-release
...@@ -1454,9 +1454,9 @@ ...@@ -1454,9 +1454,9 @@
<key>archive</key> <key>archive</key>
<map> <map>
<key>hash</key> <key>hash</key>
<string>faa1e5b7cf70c143caabe190fa5588ce</string> <string>fddd634dec5ec03924d62cc774f7f8ea</string>
<key>url</key> <key>url</key>
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearance_viewer-update-llappearance-utility/rev/304432/arch/Linux/installer/llappearance_utility-0.0.1-linux-304432.tar.bz2</string> <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/p64_viewer-llappearance-utility/rev/317266/arch/Linux/installer/llappearance_utility-0.0.1-linux-317266.tar.bz2</string>
</map> </map>
<key>name</key> <key>name</key>
<string>linux</string> <string>linux</string>
...@@ -1484,11 +1484,11 @@ ...@@ -1484,11 +1484,11 @@
<key>archive</key> <key>archive</key>
<map> <map>
<key>hash</key> <key>hash</key>
<string>29a1f64df46094eda0d681821a98d17e</string> <string>db992d58c46c80df7d4d31f8a4784b98</string>
<key>hash_algorithm</key> <key>hash_algorithm</key>
<string>md5</string> <string>md5</string>
<key>url</key> <key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/311349/arch/Darwin/installer/llceflib-1.5.3.311349-darwin-311349.tar.bz2</string> <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/317959/arch/Darwin/installer/llceflib-1.5.3.317959-darwin-317959.tar.bz2</string>
</map> </map>
<key>name</key> <key>name</key>
<string>darwin</string> <string>darwin</string>
...@@ -1498,18 +1498,18 @@ ...@@ -1498,18 +1498,18 @@
<key>archive</key> <key>archive</key>
<map> <map>
<key>hash</key> <key>hash</key>
<string>827b7c339a2cd401d9d23f9ee02cb83f</string> <string>bb3818628131a99cd789febfad9dc2c2</string>
<key>hash_algorithm</key> <key>hash_algorithm</key>
<string>md5</string> <string>md5</string>
<key>url</key> <key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/311349/arch/CYGWIN/installer/llceflib-1.5.3.311349-windows-311349.tar.bz2</string> <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/317959/arch/CYGWIN/installer/llceflib-1.5.3.317959-windows-317959.tar.bz2</string>
</map> </map>
<key>name</key> <key>name</key>
<string>windows</string> <string>windows</string>
</map> </map>
</map> </map>
<key>version</key> <key>version</key>
<string>1.5.3.311349</string> <string>1.5.3.317959</string>
</map> </map>
<key>llphysicsextensions_source</key> <key>llphysicsextensions_source</key>
<map> <map>
...@@ -2135,6 +2135,46 @@ ...@@ -2135,6 +2135,46 @@
<key>version</key> <key>version</key>
<string>0.8.0.1</string> <string>0.8.0.1</string>
</map> </map>
<key>vlc-bin</key>
<map>
<key>copyright</key>
<string>Copyright (C) 1998-2016 VLC authors and VideoLAN</string>
<key>license</key>
<string>GPL2</string>
<key>license_file</key>
<string>LICENSES/vlc.txt</string>
<key>name</key>
<string>vlc-bin</string>
<key>platforms</key>
<map>
<key>linux</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>2f410640df3f9812d1abff02a414cfa8</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-vlc-bin/rev/315283/arch/Linux/vlc_bin-2.2.3-linux-201606011750-r10.tar.bz2</string>
</map>
<key>name</key>
<string>linux</string>
</map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>04cff37070a5f65f3652b4ddcec7183f</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-vlc-bin/rev/317935/arch/CYGWIN/installer/vlc_bin-2.2.4.317935-windows-317935.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
</map>
<key>version</key>
<string>2.2.4.317935</string>
</map>
<key>xmlrpc-epi</key> <key>xmlrpc-epi</key>
<map> <map>
<key>copyright</key> <key>copyright</key>
......
...@@ -24,7 +24,6 @@ set(cmake_SOURCE_FILES ...@@ -24,7 +24,6 @@ set(cmake_SOURCE_FILES
DirectX.cmake DirectX.cmake
DragDrop.cmake DragDrop.cmake
EXPAT.cmake EXPAT.cmake
## ExamplePlugin.cmake
FindAPR.cmake FindAPR.cmake
FindAutobuild.cmake FindAutobuild.cmake
FindBerkeleyDB.cmake FindBerkeleyDB.cmake
...@@ -100,6 +99,7 @@ set(cmake_SOURCE_FILES ...@@ -100,6 +99,7 @@ set(cmake_SOURCE_FILES
Variables.cmake Variables.cmake
ViewerMiscLibs.cmake ViewerMiscLibs.cmake
VisualLeakDetector.cmake VisualLeakDetector.cmake
LibVLCPlugin.cmake
XmlRpcEpi.cmake XmlRpcEpi.cmake
ZLIB.cmake ZLIB.cmake
) )
......
...@@ -18,7 +18,7 @@ else (USESYSTEMLIBS) ...@@ -18,7 +18,7 @@ else (USESYSTEMLIBS)
use_prebuilt_binary(SDL) use_prebuilt_binary(SDL)
set (SDL_FOUND TRUE) set (SDL_FOUND TRUE)
set (SDL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/i686-linux) set (SDL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/i686-linux)
set (SDL_LIBRARY SDL directfb fusion direct) set (SDL_LIBRARY SDL directfb fusion direct X11)
endif (LINUX) endif (LINUX)
endif (USESYSTEMLIBS) endif (USESYSTEMLIBS)
......
# -*- cmake -*-
include(Linking)
include(Prebuilt)
if (USESYSTEMLIBS)
set(LIBVLCPLUGIN OFF CACHE BOOL
"LIBVLCPLUGIN support for the llplugin/llmedia test apps.")
else (USESYSTEMLIBS)
use_prebuilt_binary(vlc-bin)
set(LIBVLCPLUGIN ON CACHE BOOL
"LIBVLCPLUGIN support for the llplugin/llmedia test apps.")
set(VLC_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/vlc)
endif (USESYSTEMLIBS)
if (WINDOWS)
set(VLC_PLUGIN_LIBRARIES
libvlc.lib
libvlccore.lib
)
elseif (DARWIN)
elseif (LINUX)
# Specify a full path to make sure we get a static link
set(VLC_PLUGIN_LIBRARIES
${LIBS_PREBUILT_DIR}/lib/libvlc.a
${LIBS_PREBUILT_DIR}/lib/libvlccore.a
)
endif (WINDOWS)
2014-02-25 10:34 2014-02-25 10:34
...@@ -51,7 +51,7 @@ int main(int argc, char **argv) ...@@ -51,7 +51,7 @@ int main(int argc, char **argv)
return 1; return 1;
} }
app.mainLoop(); app.frame();
app.cleanup(); app.cleanup();
LL_INFOS() << "Crash reporter finished normally." << LL_ENDL; LL_INFOS() << "Crash reporter finished normally." << LL_ENDL;
return 0; return 0;
......
...@@ -114,7 +114,7 @@ void LLCrashLoggerLinux::gatherPlatformSpecificFiles() ...@@ -114,7 +114,7 @@ void LLCrashLoggerLinux::gatherPlatformSpecificFiles()
{ {
} }
bool LLCrashLoggerLinux::mainLoop() bool LLCrashLoggerLinux::frame()
{ {
bool send_logs = true; bool send_logs = true;
if(CRASH_BEHAVIOR_ASK == getCrashBehavior()) if(CRASH_BEHAVIOR_ASK == getCrashBehavior())
......
...@@ -36,7 +36,7 @@ class LLCrashLoggerLinux : public LLCrashLogger ...@@ -36,7 +36,7 @@ class LLCrashLoggerLinux : public LLCrashLogger
public: public:
LLCrashLoggerLinux(void); LLCrashLoggerLinux(void);
~LLCrashLoggerLinux(void); ~LLCrashLoggerLinux(void);
virtual bool mainLoop(); virtual bool frame();
virtual void updateApplication(const std::string& = LLStringUtil::null); virtual void updateApplication(const std::string& = LLStringUtil::null);
virtual void gatherPlatformSpecificFiles(); virtual void gatherPlatformSpecificFiles();
virtual bool cleanup(); virtual bool cleanup();
......
...@@ -58,6 +58,7 @@ set(llcommon_SOURCE_FILES ...@@ -58,6 +58,7 @@ set(llcommon_SOURCE_FILES
lleventfilter.cpp lleventfilter.cpp
llevents.cpp llevents.cpp
lleventtimer.cpp lleventtimer.cpp
llexception.cpp
llfasttimer.cpp llfasttimer.cpp
llfile.cpp llfile.cpp
llfindlocale.cpp llfindlocale.cpp
...@@ -157,6 +158,7 @@ set(llcommon_HEADER_FILES ...@@ -157,6 +158,7 @@ set(llcommon_HEADER_FILES
lleventfilter.h lleventfilter.h
llevents.h llevents.h
lleventemitter.h lleventemitter.h
llexception.h
llfasttimer.h llfasttimer.h
llfile.h llfile.h
llfindlocale.h llfindlocale.h
...@@ -315,7 +317,7 @@ if (LL_TESTS) ...@@ -315,7 +317,7 @@ if (LL_TESTS)
LL_ADD_INTEGRATION_TEST(llprocinfo "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llprocinfo "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lltrace "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lltrace "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
...@@ -328,6 +330,11 @@ if (LL_TESTS) ...@@ -328,6 +330,11 @@ if (LL_TESTS)
LL_ADD_INTEGRATION_TEST(llleap "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llleap "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}")
## llexception_test.cpp isn't a regression test, and doesn't need to be run
## every build. It's to help a developer make implementation choices about
## throwing and catching exceptions.
##LL_ADD_INTEGRATION_TEST(llexception "" "${test_libs}")
# *TODO - reenable these once tcmalloc libs no longer break the build. # *TODO - reenable these once tcmalloc libs no longer break the build.
#ADD_BUILD_TEST(llallocator llcommon) #ADD_BUILD_TEST(llallocator llcommon)
#ADD_BUILD_TEST(llallocator_heap_profile llcommon) #ADD_BUILD_TEST(llallocator_heap_profile llcommon)
......
...@@ -172,12 +172,12 @@ class LL_COMMON_API LLApp ...@@ -172,12 +172,12 @@ class LL_COMMON_API LLApp
virtual bool cleanup() = 0; // Override to do application cleanup virtual bool cleanup() = 0; // Override to do application cleanup
// //
// mainLoop() // frame()
// //
// Runs the application main loop. It's assumed that when you exit // Pass control to the application for a single frame. Returns 'done'
// this method, the application is in one of the cleanup states, either QUITTING or ERROR // flag: if frame() returns false, it expects to be called again.
// //
virtual bool mainLoop() = 0; // Override for the application main loop. Needs to at least gracefully notice the QUITTING state and exit. virtual bool frame() = 0; // Override for application body logic
// //
// Crash logging // Crash logging
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "llevents.h" #include "llevents.h"
#include "llerror.h" #include "llerror.h"
#include "stringize.h" #include "stringize.h"
#include "llexception.h"
// do nothing, when we need nothing done // do nothing, when we need nothing done
void LLCoros::no_cleanup(CoroData*) {} void LLCoros::no_cleanup(CoroData*) {}
...@@ -131,9 +132,9 @@ bool LLCoros::cleanup(const LLSD&) ...@@ -131,9 +132,9 @@ bool LLCoros::cleanup(const LLSD&)
if ((previousCount < 5) || !(previousCount % 50)) if ((previousCount < 5) || !(previousCount % 50))
{ {
if (previousCount < 5) if (previousCount < 5)
LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL; LL_DEBUGS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL;
else else
LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << "("<< previousCount << ")" << LL_ENDL; LL_DEBUGS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << "("<< previousCount << ")" << LL_ENDL;
} }
// The erase() call will invalidate its passed iterator value -- // The erase() call will invalidate its passed iterator value --
...@@ -185,9 +186,9 @@ std::string LLCoros::generateDistinctName(const std::string& prefix) const ...@@ -185,9 +186,9 @@ std::string LLCoros::generateDistinctName(const std::string& prefix) const
if ((previousCount < 5) || !(previousCount % 50)) if ((previousCount < 5) || !(previousCount % 50))
{ {
if (previousCount < 5) if (previousCount < 5)
LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL; LL_DEBUGS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL;
else else
LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << "(" << previousCount << ")" << LL_ENDL; LL_DEBUGS("LLCoros") << "LLCoros: launching coroutine " << name << "(" << previousCount << ")" << LL_ENDL;
} }
...@@ -223,7 +224,7 @@ std::string LLCoros::getName() const ...@@ -223,7 +224,7 @@ std::string LLCoros::getName() const
void LLCoros::setStackSize(S32 stacksize) void LLCoros::setStackSize(S32 stacksize)
{ {
LL_INFOS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL; LL_DEBUGS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL;
mStackSize = stacksize; mStackSize = stacksize;
} }
...@@ -235,7 +236,23 @@ void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& calla ...@@ -235,7 +236,23 @@ void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& calla
// capture the 'self' param in CoroData // capture the 'self' param in CoroData
data->mSelf = &self; data->mSelf = &self;
// run the code the caller actually wants in the coroutine // run the code the caller actually wants in the coroutine
callable(); try
{
callable();
}
catch (const LLContinueError&)
{
// Any uncaught exception derived from LLContinueError will be caught
// here and logged. This coroutine will terminate but the rest of the
// viewer will carry on.
LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << data->mName));
}
catch (...)
{
// Any OTHER kind of uncaught exception will cause the viewer to
// crash, hopefully informatively.
CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << data->mName));
}
// This cleanup isn't perfectly symmetrical with the way we initially set // This cleanup isn't perfectly symmetrical with the way we initially set
// data->mPrev, but this is our last chance to reset mCurrentCoro. // data->mPrev, but this is our last chance to reset mCurrentCoro.
sCurrentCoro.reset(data->mPrev); sCurrentCoro.reset(data->mPrev);
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <boost/graph/topological_sort.hpp> #include <boost/graph/topological_sort.hpp>
#include <boost/graph/exception.hpp> #include <boost/graph/exception.hpp>
// other Linden headers // other Linden headers
#include "llexception.h"
LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const EdgeList& edges) const LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const EdgeList& edges) const
{ {
...@@ -76,7 +77,7 @@ LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const ...@@ -76,7 +77,7 @@ LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const
// Omit independent nodes: display only those that might contribute to // Omit independent nodes: display only those that might contribute to
// the cycle. // the cycle.
describe(out, false); describe(out, false);
throw Cycle(out.str()); LLTHROW(Cycle(out.str()));
} }
// A peculiarity of boost::topological_sort() is that it emits results in // A peculiarity of boost::topological_sort() is that it emits results in
// REVERSE topological order: to get the result you want, you must // REVERSE topological order: to get the result you want, you must
......
...@@ -34,13 +34,13 @@ ...@@ -34,13 +34,13 @@
#include <vector> #include <vector>
#include <set> #include <set>
#include <map> #include <map>
#include <stdexcept>
#include <iosfwd> #include <iosfwd>
#include <boost/iterator/transform_iterator.hpp> #include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/indirect_iterator.hpp> #include <boost/iterator/indirect_iterator.hpp>
#include <boost/range/iterator_range.hpp> #include <boost/range/iterator_range.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include "llexception.h"
/***************************************************************************** /*****************************************************************************
* Utilities * Utilities
...@@ -106,9 +106,9 @@ class LL_COMMON_API LLDependenciesBase ...@@ -106,9 +106,9 @@ class LL_COMMON_API LLDependenciesBase
/** /**
* Exception thrown by sort() if there's a cycle * Exception thrown by sort() if there's a cycle
*/ */
struct Cycle: public std::runtime_error struct Cycle: public LLException
{ {
Cycle(const std::string& what): std::runtime_error(what) {} Cycle(const std::string& what): LLException(what) {}
}; };
/** /**
......
...@@ -174,7 +174,8 @@ namespace LLError ...@@ -174,7 +174,8 @@ namespace LLError
// not really a level // not really a level
// used to indicate that no messages should be logged // used to indicate that no messages should be logged
}; };
// If you change ELevel, please update llvlog() macro below.
/* Macro support /* Macro support
The classes CallSite and Log are used by the logging macros below. The classes CallSite and Log are used by the logging macros below.
They are not intended for general use. They are not intended for general use.
...@@ -305,24 +306,38 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; ...@@ -305,24 +306,38 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
///////////////////////////////// /////////////////////////////////
// Error Logging Macros // Error Logging Macros
// See top of file for common usage. // See top of file for common usage.
///////////////////////////////// /////////////////////////////////
// this macro uses a one-shot do statement to avoid parsing errors when writing control flow statements // Instead of using LL_DEBUGS(), LL_INFOS() et al., it may be tempting to
// without braces: // directly code the lllog() macro so you can pass in the LLError::ELevel as a
// if (condition) LL_INFOS() << "True" << LL_ENDL; else LL_INFOS()() << "False" << LL_ENDL // variable. DON'T DO IT! The reason is that the first time control passes
// through lllog(), it initializes a local static LLError::CallSite with that
#define lllog(level, once, ...) \ // *first* ELevel value. All subsequent visits will decide whether or not to
do { \ // emit output based on the *first* ELevel value bound into that static
const char* tags[] = {"", ##__VA_ARGS__}; \ // CallSite instance. Use LL_VLOGS() instead. lllog() assumes its ELevel
::size_t tag_count = LL_ARRAY_SIZE(tags) - 1; \ // argument never varies.
static LLError::CallSite _site( \
level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, once, &tags[1], tag_count);\ // this macro uses a one-shot do statement to avoid parsing errors when
if (LL_UNLIKELY(_site.shouldLog())) \ // writing control flow statements without braces:
{ \ // if (condition) LL_INFOS() << "True" << LL_ENDL; else LL_INFOS()() << "False" << LL_ENDL;
std::ostringstream* _out = LLError::Log::out(); \
#define lllog(level, once, ...) \
do { \
const char* tags[] = {"", ##__VA_ARGS__}; \
static LLError::CallSite _site(lllog_site_args_(level, once, tags)); \
lllog_test_()
#define lllog_test_() \
if (LL_UNLIKELY(_site.shouldLog())) \
{ \
std::ostringstream* _out = LLError::Log::out(); \
(*_out) (*_out)
#define lllog_site_args_(level, once, tags) \
level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), \
__FUNCTION__, once, &tags[1], LL_ARRAY_SIZE(tags)-1
//Use this construct if you need to do computation in the middle of a //Use this construct if you need to do computation in the middle of a
//message: //message:
// //
...@@ -363,4 +378,46 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; ...@@ -363,4 +378,46 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
#define LL_INFOS_ONCE(...) lllog(LLError::LEVEL_INFO, true, ##__VA_ARGS__) #define LL_INFOS_ONCE(...) lllog(LLError::LEVEL_INFO, true, ##__VA_ARGS__)
#define LL_WARNS_ONCE(...) lllog(LLError::LEVEL_WARN, true, ##__VA_ARGS__) #define LL_WARNS_ONCE(...) lllog(LLError::LEVEL_WARN, true, ##__VA_ARGS__)
// Use this if you need to pass LLError::ELevel as a variable.
#define LL_VLOGS(level, ...) llvlog(level, false, ##__VA_ARGS__)
#define LL_VLOGS_ONCE(level, ...) llvlog(level, true, ##__VA_ARGS__)
// The problem with using lllog() with a variable level is that the first time
// through, it initializes a static CallSite instance with whatever level you
// pass. That first level is bound into the CallSite; the level parameter is
// never again examined. One approach to variable level would be to
// dynamically construct a CallSite instance every call -- which could get
// expensive, depending on context. So instead, initialize a static CallSite
// for each level value we support, then dynamically select the CallSite
// instance for the passed level value.
// Compare implementation to lllog() above.
#define llvlog(level, once, ...) \
do { \
const char* tags[] = {"", ##__VA_ARGS__}; \
/* Need a static CallSite instance per expected ELevel value. */ \
/* Since we intend to index this array with the ELevel, */ \
/* _sites[0] should be ELevel(0), and so on -- avoid using */ \
/* ELevel symbolic names when initializing -- except for */ \
/* the last entry, which handles anything beyond the end. */ \
/* (Commented ELevel value names are from 2016-09-01.) */ \
/* Passing an ELevel past the end of this array is itself */ \
/* a fatal error, so ensure the last is LEVEL_ERROR. */ \
static LLError::CallSite _sites[] = \
{ \
/* LEVEL_DEBUG */ \
LLError::CallSite(lllog_site_args_(LLError::ELevel(0), once, tags)), \
/* LEVEL_INFO */ \
LLError::CallSite(lllog_site_args_(LLError::ELevel(1), once, tags)), \
/* LEVEL_WARN */ \
LLError::CallSite(lllog_site_args_(LLError::ELevel(2), once, tags)), \
/* LEVEL_ERROR */ \
LLError::CallSite(lllog_site_args_(LLError::LEVEL_ERROR, once, tags)) \
}; \
/* Clamp the passed 'level' to at most last entry */ \
std::size_t which((std::size_t(level) >= LL_ARRAY_SIZE(_sites)) ? \
(LL_ARRAY_SIZE(_sites) - 1) : std::size_t(level)); \
/* selected CallSite *must* be named _site for LL_ENDL */ \
LLError::CallSite& _site(_sites[which]); \
lllog_test_()
#endif // LL_LLERROR_H #endif // LL_LLERROR_H
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include "llerror.h" #include "llerror.h"
#include "llcoros.h" #include "llcoros.h"
#include "llmake.h" #include "llmake.h"
#include "llexception.h"
#include "lleventfilter.h" #include "lleventfilter.h"
...@@ -351,7 +352,7 @@ LLSD errorException(const LLEventWithID& result, const std::string& desc) ...@@ -351,7 +352,7 @@ LLSD errorException(const LLEventWithID& result, const std::string& desc)
// returning it, deliver it via exception. // returning it, deliver it via exception.
if (result.second) if (result.second)
{ {
throw LLErrorEvent(desc, result.first); LLTHROW(LLErrorEvent(desc, result.first));
} }
// That way, our caller knows a simple return must be from the reply // That way, our caller knows a simple return must be from the reply
// pump (pump 0). // pump (pump 0).
......
...@@ -31,10 +31,10 @@ ...@@ -31,10 +31,10 @@
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <string> #include <string>
#include <stdexcept>
#include <utility> // std::pair #include <utility> // std::pair
#include "llevents.h" #include "llevents.h"
#include "llerror.h" #include "llerror.h"
#include "llexception.h"
/** /**
* Like LLListenerOrPumpName, this is a class intended for parameter lists: * Like LLListenerOrPumpName, this is a class intended for parameter lists:
...@@ -234,11 +234,11 @@ LLSD errorException(const LLEventWithID& result, const std::string& desc); ...@@ -234,11 +234,11 @@ LLSD errorException(const LLEventWithID& result, const std::string& desc);
* because it's not an error in event processing: rather, this exception * because it's not an error in event processing: rather, this exception
* announces an event that bears error information (for some other API). * announces an event that bears error information (for some other API).
*/ */
class LL_COMMON_API LLErrorEvent: public std::runtime_error class LL_COMMON_API LLErrorEvent: public LLException
{ {
public: public:
LLErrorEvent(const std::string& what, const LLSD& data): LLErrorEvent(const std::string& what, const LLSD& data):
std::runtime_error(what), LLException(what),
mData(data) mData(data)
{} {}
virtual ~LLErrorEvent() throw() {} virtual ~LLErrorEvent() throw() {}
......
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
#include "stringize.h" #include "stringize.h"
#include "llerror.h" #include "llerror.h"
#include "llsdutil.h" #include "llsdutil.h"
#include "llexception.h"
#if LL_MSVC #if LL_MSVC
#pragma warning (disable : 4702) #pragma warning (disable : 4702)
#endif #endif
...@@ -174,7 +175,7 @@ std::string LLEventPumps::registerNew(const LLEventPump& pump, const std::string ...@@ -174,7 +175,7 @@ std::string LLEventPumps::registerNew(const LLEventPump& pump, const std::string
// Unless we're permitted to tweak it, that's Bad. // Unless we're permitted to tweak it, that's Bad.
if (! tweak) if (! tweak)
{ {
throw LLEventPump::DupPumpName(std::string("Duplicate LLEventPump name '") + name + "'"); LLTHROW(LLEventPump::DupPumpName("Duplicate LLEventPump name '" + name + "'"));
} }
// The passed name isn't unique, but we're permitted to tweak it. Find the // The passed name isn't unique, but we're permitted to tweak it. Find the
// first decimal-integer suffix not already taken. The insert() attempt // first decimal-integer suffix not already taken. The insert() attempt
...@@ -335,8 +336,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL ...@@ -335,8 +336,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
// is only when the existing connection object is still connected. // is only when the existing connection object is still connected.
if (found != mConnections.end() && found->second.connected()) if (found != mConnections.end() && found->second.connected())
{ {
throw DupListenerName(std::string("Attempt to register duplicate listener name '") + name + LLTHROW(DupListenerName("Attempt to register duplicate listener name '" + name +
"' on " + typeid(*this).name() + " '" + getName() + "'"); "' on " + typeid(*this).name() + " '" + getName() + "'"));
} }
// Okay, name is unique, try to reconcile its dependencies. Specify a new // Okay, name is unique, try to reconcile its dependencies. Specify a new
// "node" value that we never use for an mSignal placement; we'll fix it // "node" value that we never use for an mSignal placement; we'll fix it
...@@ -362,8 +363,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL ...@@ -362,8 +363,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
// unsortable. If we leave the new node in mDeps, it will continue // unsortable. If we leave the new node in mDeps, it will continue
// to screw up all future attempts to sort()! Pull it out. // to screw up all future attempts to sort()! Pull it out.
mDeps.remove(name); mDeps.remove(name);
throw Cycle(std::string("New listener '") + name + "' on " + typeid(*this).name() + LLTHROW(Cycle("New listener '" + name + "' on " + typeid(*this).name() +
" '" + getName() + "' would cause cycle: " + e.what()); " '" + getName() + "' would cause cycle: " + e.what()));
} }
// Walk the list to verify that we haven't changed the order. // Walk the list to verify that we haven't changed the order.
float previous = 0.0, myprev = 0.0; float previous = 0.0, myprev = 0.0;
...@@ -427,7 +428,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL ...@@ -427,7 +428,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
// NOW remove the offending listener node. // NOW remove the offending listener node.
mDeps.remove(name); mDeps.remove(name);
// Having constructed a description of the order change, inform caller. // Having constructed a description of the order change, inform caller.
throw OrderChange(out.str()); LLTHROW(OrderChange(out.str()));
} }
// This node becomes the previous one. // This node becomes the previous one.
previous = dmi->second; previous = dmi->second;
...@@ -627,7 +628,7 @@ bool LLListenerOrPumpName::operator()(const LLSD& event) const ...@@ -627,7 +628,7 @@ bool LLListenerOrPumpName::operator()(const LLSD& event) const
{ {
if (! mListener) if (! mListener)
{ {
throw Empty("attempting to call uninitialized"); LLTHROW(Empty("attempting to call uninitialized"));
} }
return (*mListener)(event); return (*mListener)(event);
} }
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include <set> #include <set>
#include <vector> #include <vector>
#include <deque> #include <deque>
#include <stdexcept>
#if LL_WINDOWS #if LL_WINDOWS
#pragma warning (push) #pragma warning (push)
#pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch #pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
...@@ -62,6 +61,7 @@ ...@@ -62,6 +61,7 @@
#include "llsingleton.h" #include "llsingleton.h"
#include "lldependencies.h" #include "lldependencies.h"
#include "llstl.h" #include "llstl.h"
#include "llexception.h"
/*==========================================================================*| /*==========================================================================*|
// override this to allow binding free functions with more parameters // override this to allow binding free functions with more parameters
...@@ -95,12 +95,32 @@ struct LLStopWhenHandled ...@@ -95,12 +95,32 @@ struct LLStopWhenHandled
result_type operator()(InputIterator first, InputIterator last) const result_type operator()(InputIterator first, InputIterator last) const
{ {
for (InputIterator si = first; si != last; ++si) for (InputIterator si = first; si != last; ++si)
{ {
if (*si) try
{ {
return true; if (*si)
} {
} return true;
}
}
catch (const LLContinueError&)
{
// We catch LLContinueError here because an LLContinueError-
// based exception means the viewer as a whole should carry on
// to the best of our ability. Therefore subsequent listeners
// on the same LLEventPump should still receive this event.
// The iterator passed to a boost::signals2 Combiner is very
// clever, but provides no contextual information. We would
// very much like to be able to log the name of the LLEventPump
// plus the name of this particular listener, but alas.
LOG_UNHANDLED_EXCEPTION("LLEventPump");
}
// We do NOT catch (...) here because we might as well let it
// propagate out to the generic handler. If we were able to log
// context information here, that would be great, but we can't, so
// there's no point.
}
return false; return false;
} }
}; };
...@@ -188,10 +208,10 @@ class LL_COMMON_API LLListenerOrPumpName ...@@ -188,10 +208,10 @@ class LL_COMMON_API LLListenerOrPumpName
bool operator()(const LLSD& event) const; bool operator()(const LLSD& event) const;
/// exception if you try to call when empty /// exception if you try to call when empty
struct Empty: public std::runtime_error struct Empty: public LLException
{ {
Empty(const std::string& what): Empty(const std::string& what):
std::runtime_error(std::string("LLListenerOrPumpName::Empty: ") + what) {} LLException(std::string("LLListenerOrPumpName::Empty: ") + what) {}
}; };
private: private:
...@@ -373,10 +393,10 @@ class LL_COMMON_API LLEventPump: public LLEventTrackable ...@@ -373,10 +393,10 @@ class LL_COMMON_API LLEventPump: public LLEventTrackable
* you didn't pass <tt>tweak=true</tt> to permit it to generate a unique * you didn't pass <tt>tweak=true</tt> to permit it to generate a unique
* variant. * variant.
*/ */
struct DupPumpName: public std::runtime_error struct DupPumpName: public LLException
{ {
DupPumpName(const std::string& what): DupPumpName(const std::string& what):
std::runtime_error(std::string("DupPumpName: ") + what) {} LLException(std::string("DupPumpName: ") + what) {}
}; };
/** /**
...@@ -401,9 +421,9 @@ class LL_COMMON_API LLEventPump: public LLEventTrackable ...@@ -401,9 +421,9 @@ class LL_COMMON_API LLEventPump: public LLEventTrackable
/// group exceptions thrown by listen(). We use exceptions because these /// group exceptions thrown by listen(). We use exceptions because these
/// particular errors are likely to be coding errors, found and fixed by /// particular errors are likely to be coding errors, found and fixed by
/// the developer even before preliminary checkin. /// the developer even before preliminary checkin.
struct ListenError: public std::runtime_error struct ListenError: public LLException
{ {
ListenError(const std::string& what): std::runtime_error(what) {} ListenError(const std::string& what): LLException(what) {}
}; };
/** /**
* exception thrown by listen(). You are attempting to register a * exception thrown by listen(). You are attempting to register a
......
/**
* @file llexception.cpp
* @author Nat Goodspeed
* @date 2016-08-12
* @brief Implementation for llexception.
*
* $LicenseInfo:firstyear=2016&license=viewerlgpl$
* Copyright (c) 2016, Linden Research, Inc.
* $/LicenseInfo$
*/
// Precompiled header
#include "linden_common.h"
// associated header
#include "llexception.h"
// STL headers
// std headers
#include <typeinfo>
// external library headers
#include <boost/exception/diagnostic_information.hpp>
// other Linden headers
#include "llerror.h"
#include "llerrorcontrol.h"
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 std::string& context)
{
// log same message but allow caller-specified severity level
LL_VLOGS(level, "LLException") << LLError::abbreviateFile(file)
<< "(" << line << "): Unhandled exception caught in " << 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,
const std::string& context)
{
// LL_ERRS() terminates and propagates message into crash dump.
log_unhandled_exception_(LLError::LEVEL_ERROR, file, line, pretty_function, context);
}
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, context);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment