diff options
| author | Nat Goodspeed <nat@lindenlab.com> | 2016-08-17 11:41:12 -0400 | 
|---|---|---|
| committer | Nat Goodspeed <nat@lindenlab.com> | 2016-08-17 11:41:12 -0400 | 
| commit | e72bdc9bc5895267f77bf3eac8d68f82f5e2806b (patch) | |
| tree | bb86f9ae3e199a994ec5e2255d9af0de3fa17c95 | |
| parent | 4fb100ac7a33174883184f1320d0beac08ead3a7 (diff) | |
| parent | 5e9d2f57c82a57307a48afea09aa539b9fa80abf (diff) | |
Automated merge with ssh://bitbucket.org/lindenlab/viewer-release
53 files changed, 902 insertions, 448 deletions
| diff --git a/autobuild.xml b/autobuild.xml index 072dfa678a..e9928908be 100755 --- a/autobuild.xml +++ b/autobuild.xml @@ -1454,9 +1454,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>faa1e5b7cf70c143caabe190fa5588ce</string> +              <string>fddd634dec5ec03924d62cc774f7f8ea</string>                <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>              <key>name</key>              <string>linux</string> diff --git a/indra/linux_crash_logger/linux_crash_logger.cpp b/indra/linux_crash_logger/linux_crash_logger.cpp index 9d5ec33fed..63e5409876 100644 --- a/indra/linux_crash_logger/linux_crash_logger.cpp +++ b/indra/linux_crash_logger/linux_crash_logger.cpp @@ -51,7 +51,7 @@ int main(int argc, char **argv)  		return 1;  	} -	app.mainLoop(); +	app.frame();  	app.cleanup();  	LL_INFOS() << "Crash reporter finished normally." << LL_ENDL;  	return 0; diff --git a/indra/linux_crash_logger/llcrashloggerlinux.cpp b/indra/linux_crash_logger/llcrashloggerlinux.cpp index e2d2e7ff26..4092d43fc5 100644 --- a/indra/linux_crash_logger/llcrashloggerlinux.cpp +++ b/indra/linux_crash_logger/llcrashloggerlinux.cpp @@ -114,7 +114,7 @@ void LLCrashLoggerLinux::gatherPlatformSpecificFiles()  {  } -bool LLCrashLoggerLinux::mainLoop() +bool LLCrashLoggerLinux::frame()  {  	bool send_logs = true;  	if(CRASH_BEHAVIOR_ASK == getCrashBehavior()) diff --git a/indra/linux_crash_logger/llcrashloggerlinux.h b/indra/linux_crash_logger/llcrashloggerlinux.h index dae6c46651..789f6f03f5 100644 --- a/indra/linux_crash_logger/llcrashloggerlinux.h +++ b/indra/linux_crash_logger/llcrashloggerlinux.h @@ -36,7 +36,7 @@ class LLCrashLoggerLinux : public LLCrashLogger  public:  	LLCrashLoggerLinux(void);  	~LLCrashLoggerLinux(void); -	virtual bool mainLoop(); +	virtual bool frame();  	virtual void updateApplication(const std::string& = LLStringUtil::null);  	virtual void gatherPlatformSpecificFiles();  	virtual bool cleanup(); diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 907dbab8f8..410a5819b3 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -58,6 +58,7 @@ set(llcommon_SOURCE_FILES      lleventfilter.cpp      llevents.cpp      lleventtimer.cpp +    llexception.cpp      llfasttimer.cpp      llfile.cpp      llfindlocale.cpp @@ -157,6 +158,7 @@ set(llcommon_HEADER_FILES      lleventfilter.h      llevents.h      lleventemitter.h +    llexception.h      llfasttimer.h      llfile.h      llfindlocale.h @@ -315,7 +317,7 @@ if (LL_TESTS)    LL_ADD_INTEGRATION_TEST(llprocinfo "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(llrand "" "${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(lltrace "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}") @@ -328,6 +330,11 @@ if (LL_TESTS)    LL_ADD_INTEGRATION_TEST(llleap "" "${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.    #ADD_BUILD_TEST(llallocator llcommon)    #ADD_BUILD_TEST(llallocator_heap_profile llcommon) diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index d9933b3d36..ff9a92b45f 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -172,12 +172,12 @@ public:  	virtual bool cleanup() = 0;			// Override to do application cleanup  	// -	// mainLoop() +	// frame()  	// -	// Runs the application main loop.  It's assumed that when you exit -	// this method, the application is in one of the cleanup states, either QUITTING or ERROR +	// Pass control to the application for a single frame. Returns 'done' +	// 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 diff --git a/indra/llcommon/lldependencies.cpp b/indra/llcommon/lldependencies.cpp index 0e72c175cb..0d5757effd 100644 --- a/indra/llcommon/lldependencies.cpp +++ b/indra/llcommon/lldependencies.cpp @@ -40,6 +40,7 @@  #include <boost/graph/topological_sort.hpp>  #include <boost/graph/exception.hpp>  // other Linden headers +#include "llexception.h"  LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const EdgeList& edges) const  { @@ -76,7 +77,7 @@ LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const          // Omit independent nodes: display only those that might contribute to          // the cycle.          describe(out, false); -        throw Cycle(out.str()); +        LLTHROW(Cycle(out.str()));      }      // A peculiarity of boost::topological_sort() is that it emits results in      // REVERSE topological order: to get the result you want, you must diff --git a/indra/llcommon/lldependencies.h b/indra/llcommon/lldependencies.h index e0294e271b..125bd6a835 100644 --- a/indra/llcommon/lldependencies.h +++ b/indra/llcommon/lldependencies.h @@ -34,13 +34,13 @@  #include <vector>  #include <set>  #include <map> -#include <stdexcept>  #include <iosfwd>  #include <boost/iterator/transform_iterator.hpp>  #include <boost/iterator/indirect_iterator.hpp>  #include <boost/range/iterator_range.hpp>  #include <boost/function.hpp>  #include <boost/bind.hpp> +#include "llexception.h"  /*****************************************************************************  *   Utilities @@ -106,9 +106,9 @@ public:      /**       * 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) {}      };      /** diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp index 2d5f964deb..56367b8f54 100644 --- a/indra/llcommon/lleventcoro.cpp +++ b/indra/llcommon/lleventcoro.cpp @@ -39,6 +39,7 @@  #include "llerror.h"  #include "llcoros.h"  #include "llmake.h" +#include "llexception.h"  #include "lleventfilter.h" @@ -351,7 +352,7 @@ LLSD errorException(const LLEventWithID& result, const std::string& desc)      // returning it, deliver it via exception.      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      // pump (pump 0). diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h index 87926c692d..84827aab4a 100644 --- a/indra/llcommon/lleventcoro.h +++ b/indra/llcommon/lleventcoro.h @@ -31,10 +31,10 @@  #include <boost/optional.hpp>  #include <string> -#include <stdexcept>  #include <utility>                  // std::pair  #include "llevents.h"  #include "llerror.h" +#include "llexception.h"  /**   * Like LLListenerOrPumpName, this is a class intended for parameter lists: @@ -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   * 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:      LLErrorEvent(const std::string& what, const LLSD& data): -        std::runtime_error(what), +        LLException(what),          mData(data)      {}      virtual ~LLErrorEvent() throw() {} diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 645c29d770..19d700a3b0 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -57,6 +57,7 @@  #include "stringize.h"  #include "llerror.h"  #include "llsdutil.h" +#include "llexception.h"  #if LL_MSVC  #pragma warning (disable : 4702)  #endif @@ -174,7 +175,7 @@ std::string LLEventPumps::registerNew(const LLEventPump& pump, const std::string      // Unless we're permitted to tweak it, that's Bad.      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      // first decimal-integer suffix not already taken. The insert() attempt @@ -326,8 +327,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL      // is only when the existing connection object is still connected.      if (found != mConnections.end() && found->second.connected())      { -        throw DupListenerName(std::string("Attempt to register duplicate listener name '") + name + -                              "' on " + typeid(*this).name() + " '" + getName() + "'"); +        LLTHROW(DupListenerName("Attempt to register duplicate listener name '" + name + +                                "' on " + typeid(*this).name() + " '" + getName() + "'"));      }      // 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 @@ -353,8 +354,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL          // unsortable. If we leave the new node in mDeps, it will continue          // to screw up all future attempts to sort()! Pull it out.          mDeps.remove(name); -        throw Cycle(std::string("New listener '") + name + "' on " + typeid(*this).name() + -                    " '" + getName() + "' would cause cycle: " + e.what()); +        LLTHROW(Cycle("New listener '" + name + "' on " + typeid(*this).name() + +                      " '" + getName() + "' would cause cycle: " + e.what()));      }      // Walk the list to verify that we haven't changed the order.      float previous = 0.0, myprev = 0.0; @@ -418,7 +419,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL              // NOW remove the offending listener node.              mDeps.remove(name);              // Having constructed a description of the order change, inform caller. -            throw OrderChange(out.str()); +            LLTHROW(OrderChange(out.str()));          }          // This node becomes the previous one.          previous = dmi->second; @@ -608,7 +609,7 @@ bool LLListenerOrPumpName::operator()(const LLSD& event) const  {      if (! mListener)      { -        throw Empty("attempting to call uninitialized"); +        LLTHROW(Empty("attempting to call uninitialized"));      }      return (*mListener)(event);  } diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index ba4fcd766e..8ff337911d 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -37,7 +37,6 @@  #include <set>  #include <vector>  #include <deque> -#include <stdexcept>  #if LL_WINDOWS  	#pragma warning (push)  	#pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch @@ -62,6 +61,7 @@  #include "llsingleton.h"  #include "lldependencies.h"  #include "llstl.h" +#include "llexception.h"  /*==========================================================================*|  // override this to allow binding free functions with more parameters @@ -188,10 +188,10 @@ public:      bool operator()(const LLSD& event) const;      /// exception if you try to call when empty -    struct Empty: public std::runtime_error +    struct Empty: public LLException      {          Empty(const std::string& what): -            std::runtime_error(std::string("LLListenerOrPumpName::Empty: ") + what) {} +            LLException(std::string("LLListenerOrPumpName::Empty: ") + what) {}      };  private: @@ -371,10 +371,10 @@ public:       * you didn't pass <tt>tweak=true</tt> to permit it to generate a unique       * variant.       */ -    struct DupPumpName: public std::runtime_error +    struct DupPumpName: public LLException      {          DupPumpName(const std::string& what): -            std::runtime_error(std::string("DupPumpName: ") + what) {} +            LLException(std::string("DupPumpName: ") + what) {}      };      /** @@ -399,9 +399,9 @@ public:      /// group exceptions thrown by listen(). We use exceptions because these      /// particular errors are likely to be coding errors, found and fixed by      /// 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 diff --git a/indra/llcommon/llexception.cpp b/indra/llcommon/llexception.cpp new file mode 100644 index 0000000000..f48509b2aa --- /dev/null +++ b/indra/llcommon/llexception.cpp @@ -0,0 +1,41 @@ +/** + * @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" + +void crash_on_unhandled_exception_(const char* file, int line, const char* pretty_function) +{ +    // LL_ERRS() terminates, but also propagates message into crash dump. +    LL_ERRS() << file << "(" << line << "): Unhandled exception caught in " << pretty_function +              << ":\n" << boost::current_exception_diagnostic_information() << LL_ENDL; +} + +void log_unhandled_exception_(const char* file, int line, const char* pretty_function, +                             const LLContinueError& e) +{ +    // Use LL_WARNS() because we seriously do not expect this to happen +    // routinely, but we DO expect to return from this function. Deriving your +    // exception from LLContinueError implies that such an exception should +    // NOT be fatal to the viewer, only to its current task. +    LL_WARNS() << file << "(" << line << "): Unhandled " << typeid(e).name() +               << " exception caught in " << pretty_function +               << ":\n" << boost::current_exception_diagnostic_information() << LL_ENDL; +} diff --git a/indra/llcommon/llexception.h b/indra/llcommon/llexception.h new file mode 100644 index 0000000000..e9e25ae689 --- /dev/null +++ b/indra/llcommon/llexception.h @@ -0,0 +1,82 @@ +/** + * @file   llexception.h + * @author Nat Goodspeed + * @date   2016-06-29 + * @brief  Types needed for generic exception handling + *  + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Copyright (c) 2016, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLEXCEPTION_H) +#define LL_LLEXCEPTION_H + +#include <stdexcept> +#include <boost/exception/exception.hpp> +#include <boost/throw_exception.hpp> + +// "Found someone who can comfort me +//  But there are always exceptions..." +//  - Empty Pages, Traffic, from John Barleycorn (1970) +//    https://www.youtube.com/watch?v=dRH0CGVK7ic + +/** + * LLException is intended as the common base class from which all + * viewer-specific exceptions are derived. Rationale for why it's derived from + * both std::exception and boost::exception is explained in + * tests/llexception_test.cpp. + * + * 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(). + * + * There may be circumstances in which it would be valuable to distinguish an + * exception explicitly thrown by viewer code from an exception thrown by + * (say) a third-party library. Catching (const LLException&) supports such + * usage. However, most of the value of this base class is in the + * diagnostic_information() available via Boost.Exception. + */ +struct LLException: +    public std::runtime_error, +    public boost::exception +{ +    LLException(const std::string& what): +        std::runtime_error(what) +    {} +}; + +/** + * The point of LLContinueError is to distinguish exceptions that need not + * terminate the whole viewer session. In general, an uncaught exception will + * be logged and will crash the viewer. However, though an uncaught exception + * derived from LLContinueError will still be logged, the viewer will attempt + * to continue processing. + */ +struct LLContinueError: public LLException +{ +    LLContinueError(const std::string& what): +        LLException(what) +    {} +}; + +/** + * Please use LLTHROW() to throw viewer exceptions whenever possible. This + * enriches the exception's diagnostic_information() with the source file, + * line and containing function of the LLTHROW() macro. + */ +// Currently we implement that using BOOST_THROW_EXCEPTION(). Wrap it in +// LLTHROW() in case we ever want to revisit that implementation decision. +#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__, __PRETTY_FUNCTION__) +void crash_on_unhandled_exception_(const char*, int, const char*); + +/// Call this from a catch (const LLContinueError&) clause +#define LOG_UNHANDLED_EXCEPTION(EXC) \ +     log_unhandled_exception_(__FILE__, __LINE__, __PRETTY_FUNCTION__, EXC) +void log_unhandled_exception_(const char*, int, const char*, const LLContinueError&); + +#endif /* ! defined(LL_LLEXCEPTION_H) */ diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp index 84d2a12f65..c87d2a3e58 100644 --- a/indra/llcommon/llleap.cpp +++ b/indra/llcommon/llleap.cpp @@ -33,6 +33,7 @@  #include "lltimer.h"  #include "lluuid.h"  #include "llleaplistener.h" +#include "llexception.h"  #if LL_MSVC  #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally @@ -69,7 +70,7 @@ public:          // Rule out empty vector          if (plugin.empty())          { -            throw Error("no plugin command"); +            LLTHROW(Error("no plugin command"));          }          // Don't leave desc empty either, but in this case, if we weren't @@ -112,7 +113,7 @@ public:          // If that didn't work, no point in keeping this LLLeap object.          if (! mChild)          { -            throw Error(STRINGIZE("failed to run " << mDesc)); +            LLTHROW(Error(STRINGIZE("failed to run " << mDesc)));          }          // Okay, launch apparently worked. Change our mDonePump listener. diff --git a/indra/llcommon/llleap.h b/indra/llcommon/llleap.h index e33f25e530..8aac8a64c5 100644 --- a/indra/llcommon/llleap.h +++ b/indra/llcommon/llleap.h @@ -13,9 +13,9 @@  #define LL_LLLEAP_H  #include "llinstancetracker.h" +#include "llexception.h"  #include <string>  #include <vector> -#include <stdexcept>  /**   * LLSD Event API Plugin class. Because instances are managed by @@ -67,9 +67,9 @@ public:       * string(s) passed to create() might come from an external source. This       * way the caller can catch LLLeap::Error and try to recover.       */ -    struct Error: public std::runtime_error +    struct Error: public LLException      { -        Error(const std::string& what): std::runtime_error(what) {} +        Error(const std::string& what): LLException(what) {}      };      virtual ~LLLeap(); diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp index 44f56daf2d..8c321d06b9 100644 --- a/indra/llcommon/llprocess.cpp +++ b/indra/llcommon/llprocess.cpp @@ -34,6 +34,7 @@  #include "llapr.h"  #include "apr_signal.h"  #include "llevents.h" +#include "llexception.h"  #include <boost/foreach.hpp>  #include <boost/bind.hpp> @@ -472,9 +473,9 @@ private:  *****************************************************************************/  /// Need an exception to avoid constructing an invalid LLProcess object, but  /// internal use only -struct LLProcessError: public std::runtime_error +struct LLProcessError: public LLException  { -	LLProcessError(const std::string& msg): std::runtime_error(msg) {} +	LLProcessError(const std::string& msg): LLException(msg) {}  };  LLProcessPtr LLProcess::create(const LLSDOrParams& params) @@ -530,8 +531,8 @@ LLProcess::LLProcess(const LLSDOrParams& params):  	if (! params.validateBlock(true))  	{ -		throw LLProcessError(STRINGIZE("not launched: failed parameter validation\n" -									   << LLSDNotationStreamer(params))); +		LLTHROW(LLProcessError(STRINGIZE("not launched: failed parameter validation\n" +										 << LLSDNotationStreamer(params))));  	}  	mPostend = params.postend; @@ -596,10 +597,10 @@ LLProcess::LLProcess(const LLSDOrParams& params):  		}  		else  		{ -			throw LLProcessError(STRINGIZE("For " << params.executable() -										   << ": unsupported FileParam for " << which -										   << ": type='" << fparam.type() -										   << "', name='" << fparam.name() << "'")); +			LLTHROW(LLProcessError(STRINGIZE("For " << params.executable() +											 << ": unsupported FileParam for " << which +											 << ": type='" << fparam.type() +											 << "', name='" << fparam.name() << "'")));  		}  	}  	// By default, pass APR_NO_PIPE for unspecified slots. @@ -678,7 +679,7 @@ LLProcess::LLProcess(const LLSDOrParams& params):  	if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr,  										   gAPRPoolp)))  	{ -		throw LLProcessError(STRINGIZE(params << " failed")); +		LLTHROW(LLProcessError(STRINGIZE(params << " failed")));  	}  	// arrange to call status_callback() @@ -1063,7 +1064,7 @@ PIPETYPE& LLProcess::getPipe(FILESLOT slot)  	PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot);  	if (! wp)  	{ -		throw NoPipe(error); +		LLTHROW(NoPipe(error));  	}  	return *wp;  } diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h index 43ccadc412..bfac4567a5 100644 --- a/indra/llcommon/llprocess.h +++ b/indra/llcommon/llprocess.h @@ -30,13 +30,13 @@  #include "llinitparam.h"  #include "llsdparam.h"  #include "llwin32headerslean.h" +#include "llexception.h"  #include "apr_thread_proc.h"  #include <boost/shared_ptr.hpp>  #include <boost/ptr_container/ptr_vector.hpp>  #include <boost/optional.hpp>  #include <boost/noncopyable.hpp>  #include <iosfwd>                   // std::ostream -#include <stdexcept>  #if LL_WINDOWS  #include "llwin32headerslean.h"	// for HANDLE @@ -479,9 +479,9 @@ public:  	/// Exception thrown by getWritePipe(), getReadPipe() if you didn't ask to  	/// create a pipe at the corresponding FILESLOT. -	struct NoPipe: public std::runtime_error +	struct NoPipe: public LLException  	{ -		NoPipe(const std::string& what): std::runtime_error(what) {} +		NoPipe(const std::string& what): LLException(what) {}  	};  	/** diff --git a/indra/llcommon/llthreadsafequeue.cpp b/indra/llcommon/llthreadsafequeue.cpp index 185f0d63fb..491f920c0f 100644 --- a/indra/llcommon/llthreadsafequeue.cpp +++ b/indra/llcommon/llthreadsafequeue.cpp @@ -27,6 +27,7 @@  #include <apr_pools.h>  #include <apr_queue.h>  #include "llthreadsafequeue.h" +#include "llexception.h" @@ -41,13 +42,13 @@ LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(apr_pool_t * po  {  	if(mOwnsPool) {  		apr_status_t status = apr_pool_create(&mPool, 0); -		if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate pool"); +		if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate pool"));  	} else {  		; // No op.  	}  	apr_status_t status = apr_queue_create(&mQueue, capacity, mPool); -	if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate queue"); +	if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate queue"));  } @@ -68,9 +69,9 @@ void LLThreadSafeQueueImplementation::pushFront(void * element)  	apr_status_t status = apr_queue_push(mQueue, element);  	if(status == APR_EINTR) { -		throw LLThreadSafeQueueInterrupt(); +		LLTHROW(LLThreadSafeQueueInterrupt());  	} else if(status != APR_SUCCESS) { -		throw LLThreadSafeQueueError("push failed"); +		LLTHROW(LLThreadSafeQueueError("push failed"));  	} else {  		; // Success.  	} @@ -88,9 +89,9 @@ void * LLThreadSafeQueueImplementation::popBack(void)  	apr_status_t status = apr_queue_pop(mQueue, &element);  	if(status == APR_EINTR) { -		throw LLThreadSafeQueueInterrupt(); +		LLTHROW(LLThreadSafeQueueInterrupt());  	} else if(status != APR_SUCCESS) { -		throw LLThreadSafeQueueError("pop failed"); +		LLTHROW(LLThreadSafeQueueError("pop failed"));  	} else {  		return element;  	} diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h index 58cac38769..45289ef0b4 100644 --- a/indra/llcommon/llthreadsafequeue.h +++ b/indra/llcommon/llthreadsafequeue.h @@ -27,9 +27,8 @@  #ifndef LL_LLTHREADSAFEQUEUE_H  #define LL_LLTHREADSAFEQUEUE_H - +#include "llexception.h"  #include <string> -#include <stdexcept>  struct apr_pool_t; // From apr_pools.h @@ -40,11 +39,11 @@ class LLThreadSafeQueueImplementation; // See below.  // A general queue exception.  //  class LL_COMMON_API LLThreadSafeQueueError: -public std::runtime_error +	public LLException  {  public:  	LLThreadSafeQueueError(std::string const & message): -	std::runtime_error(message) +		LLException(message)  	{  		; // No op.  	} diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index e3671047b4..d4af2c6b01 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -83,7 +83,7 @@ unsigned int decode( char const * fiveChars ) throw( bad_input_data )  unsigned int ret = 0;  for( int ix = 0; ix < 5; ++ix ) {  char * s = strchr( encodeTable, fiveChars[ ix ] ); -if( s == 0 ) throw bad_input_data(); +if( s == 0 ) LLTHROW(bad_input_data());  ret = ret * 85 + (s-encodeTable);  }  return ret; diff --git a/indra/llcommon/tests/llexception_test.cpp b/indra/llcommon/tests/llexception_test.cpp new file mode 100644 index 0000000000..6bee1943c2 --- /dev/null +++ b/indra/llcommon/tests/llexception_test.cpp @@ -0,0 +1,308 @@ +/** + * @file   llexception_test.cpp + * @author Nat Goodspeed + * @date   2016-08-12 + * @brief  Tests for throwing exceptions. + * + * This isn't a regression test: it doesn't need to be run every build, which + * is why the corresponding line in llcommon/CMakeLists.txt is commented out. + * Rather it's a head-to-head test of what kind of exception information we + * can collect from various combinations of exception base classes, type of + * throw verb and sequences of catch clauses. + * + * This "test" makes no ensure() calls: its output goes to stdout for human + * examination. + * + * As of 2016-08-12 with Boost 1.57, we come to the following conclusions. + * These should probably be re-examined from time to time as we update Boost. + * + * - It is indisputably beneficial to use BOOST_THROW_EXCEPTION() rather than + *   plain throw. The macro annotates the exception object with the filename, + *   line number and function name from which the exception was thrown. + * + * - That being the case, deriving only from boost::exception isn't an option. + *   Every exception object passed to BOOST_THROW_EXCEPTION() must be derived + *   directly or indirectly from std::exception. The only question is whether + *   to also derive from boost::exception. We decided to derive LLException + *   from both, as it makes message output slightly cleaner, but this is a + *   trivial reason: if a strong reason emerges to prefer single inheritance, + *   dropping the boost::exception base class shouldn't be a problem. + * + * - (As you will have guessed, ridiculous things like a char* or int or a + *   class derived from neither boost::exception nor std::exception can only + *   be caught by that specific type or (...), and + *   boost::current_exception_diagnostic_information() simply throws up its + *   hands and confesses utter ignorance. Stay away from such nonsense.) + * + * - But if you derive from std::exception, to nat's surprise, + *   boost::current_exception_diagnostic_information() gives as much + *   information about exceptions in a catch (...) clause as you can get from + *   a specific catch (const std::exception&) clause, notably the concrete + *   exception class and the what() string. So instead of a sequence like + * + *   try { ... } + *   catch (const boost::exception& e) { ... boost-flavored logging ... } + *   catch (const std::exception& e)   { ... std::exception logging ... } + *   catch (...)                       { ... generic logging ... } + * + *   we should be able to get away with only a catch (...) clause that logs + *   boost::current_exception_diagnostic_information(). + * + * - Going further: boost::current_exception_diagnostic_information() provides + *   just as much information even within a std::set_terminate() handler. So + *   it might not even be strictly necessary to include a catch (...) clause + *   since the viewer does use std::set_terminate(). + * + * - (We might consider adding a catch (int) clause because Kakadu internally + *   throws ints, and who knows if one of those might leak out. If it does, + *   boost::current_exception_diagnostic_information() can do nothing with it. + *   A catch (int) clause could at least log the value and rethrow.) + * + * $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/throw_exception.hpp> +// other Linden headers +#include "../test/lltut.h" + +// helper for display output +// usage: std::cout << center(some string value, fill char, width) << std::endl; +// (assumes it's the only thing on that particular line) +struct center +{ +    center(const std::string& label, char fill, std::size_t width): +        mLabel(label), +        mFill(fill), +        mWidth(width) +    {} + +    // Use friend declaration not because we need to grant access, but because +    // it lets us declare a free operator like a member function. +    friend std::ostream& operator<<(std::ostream& out, const center& ctr) +    { +        std::size_t padded = ctr.mLabel.length() + 2; +        std::size_t left  = (ctr.mWidth - padded) / 2; +        std::size_t right = ctr.mWidth - left - padded; +        return out << std::string(left, ctr.mFill) << ' ' << ctr.mLabel << ' ' +                   << std::string(right, ctr.mFill); +    } + +    std::string mLabel; +    char mFill; +    std::size_t mWidth; +}; + +/***************************************************************************** +*   Four kinds of exceptions: derived from boost::exception, from +*   std::exception, from both, from neither +*****************************************************************************/ +// Interestingly, we can't use this variant with BOOST_THROW_EXCEPTION() +// (which we want) -- we reach a failure topped by this comment: +//  //All boost exceptions are required to derive from std::exception, +//  //to ensure compatibility with BOOST_NO_EXCEPTIONS. +struct FromBoost: public boost::exception +{ +    FromBoost(const std::string& what): mWhat(what) {} +    ~FromBoost() throw() {} +    std::string what() const { return mWhat; } +    std::string mWhat; +}; + +struct FromStd: public std::runtime_error +{ +    FromStd(const std::string& what): std::runtime_error(what) {} +}; + +struct FromBoth: public boost::exception, public std::runtime_error +{ +    FromBoth(const std::string& what): std::runtime_error(what) {} +}; + +// Same deal with FromNeither: can't use with BOOST_THROW_EXCEPTION(). +struct FromNeither +{ +    FromNeither(const std::string& what): mWhat(what) {} +    std::string what() const { return mWhat; } +    std::string mWhat; +}; + +/***************************************************************************** +*   Two kinds of throws: plain throw and BOOST_THROW_EXCEPTION() +*****************************************************************************/ +template <typename EXC> +void plain_throw(const std::string& what) +{ +    throw EXC(what); +} + +template <typename EXC> +void boost_throw(const std::string& what) +{ +    BOOST_THROW_EXCEPTION(EXC(what)); +} + +// Okay, for completeness, functions that throw non-class values. We wouldn't +// even deign to consider these if we hadn't found examples in our own source +// code! (Note that Kakadu's internal exception support is still based on +// throwing ints.) +void throw_char_ptr(const std::string& what) +{ +    throw what.c_str(); // umm... +} + +void throw_int(const std::string& what) +{ +    throw int(what.length()); +} + +/***************************************************************************** +*   Three sequences of catch clauses: +*   boost::exception then ..., +*   std::exception then ..., +*   or just ... +*****************************************************************************/ +void catch_boost_dotdotdot(void (*thrower)(const std::string&), const std::string& what) +{ +    try +    { +        thrower(what); +    } +    catch (const boost::exception& e) +    { +        std::cout << "catch (const boost::exception& e)" << std::endl; +        std::cout << "e is " << typeid(e).name() << std::endl; +        std::cout << "boost::diagnostic_information(e):\n'" +                  << boost::diagnostic_information(e) << "'" << std::endl; +        // no way to report e.what() +    } +    catch (...) +    { +        std::cout << "catch (...)" << std::endl; +        std::cout << "boost::current_exception_diagnostic_information():\n'" +                  << boost::current_exception_diagnostic_information() << "'" +                  << std::endl; +    } +} + +void catch_std_dotdotdot(void (*thrower)(const std::string&), const std::string& what) +{ +    try +    { +        thrower(what); +    } +    catch (const std::exception& e) +    { +        std::cout << "catch (const std::exception& e)" << std::endl; +        std::cout << "e is " << typeid(e).name() << std::endl; +        std::cout << "boost::diagnostic_information(e):\n'" +                  << boost::diagnostic_information(e) << "'" << std::endl; +        std::cout << "e.what: '" +                  << e.what() << "'" << std::endl; +    } +    catch (...) +    { +        std::cout << "catch (...)" << std::endl; +        std::cout << "boost::current_exception_diagnostic_information():\n'" +                  << boost::current_exception_diagnostic_information() << "'" +                  << std::endl; +    } +} + +void catch_dotdotdot(void (*thrower)(const std::string&), const std::string& what) +{ +    try +    { +        thrower(what); +    } +    catch (...) +    { +        std::cout << "catch (...)" << std::endl; +        std::cout << "boost::current_exception_diagnostic_information():\n'" +                  << boost::current_exception_diagnostic_information() << "'" +                  << std::endl; +    } +} + +/***************************************************************************** +*   Try a particular kind of throw against each of three catch sequences +*****************************************************************************/ +void catch_several(void (*thrower)(const std::string&), const std::string& what) +{ +    std::cout << std::string(20, '-') << "catch_boost_dotdotdot(" << what << ")" << std::endl; +    catch_boost_dotdotdot(thrower, "catch_boost_dotdotdot(" + what + ")"); + +    std::cout << std::string(20, '-') << "catch_std_dotdotdot(" << what << ")" << std::endl; +    catch_std_dotdotdot(thrower, "catch_std_dotdotdot(" + what + ")"); + +    std::cout << std::string(20, '-') << "catch_dotdotdot(" << what << ")" << std::endl; +    catch_dotdotdot(thrower, "catch_dotdotdot(" + what + ")"); +} + +/***************************************************************************** +*   For a particular kind of exception, try both kinds of throw against all +*   three catch sequences +*****************************************************************************/ +template <typename EXC> +void catch_both_several(const std::string& what) +{ +    std::cout << std::string(20, '*') << "plain_throw<" << what << ">" << std::endl; +    catch_several(plain_throw<EXC>, "plain_throw<" + what + ">"); + +    std::cout << std::string(20, '*') << "boost_throw<" << what << ">" << std::endl; +    catch_several(boost_throw<EXC>, "boost_throw<" + what + ">"); +} + +/***************************************************************************** +*   TUT +*****************************************************************************/ +namespace tut +{ +    struct llexception_data +    { +    }; +    typedef test_group<llexception_data> llexception_group; +    typedef llexception_group::object object; +    llexception_group llexceptiongrp("llexception"); + +    template<> template<> +    void object::test<1>() +    { +        set_test_name("throwing exceptions"); + +        // For each kind of exception, try both kinds of throw against all +        // three catch sequences +        std::size_t margin = 72; +        std::cout << center("FromStd", '=', margin) << std::endl; +        catch_both_several<FromStd>("FromStd"); + +        std::cout << center("FromBoth", '=', margin) << std::endl; +        catch_both_several<FromBoth>("FromBoth"); + +        std::cout << center("FromBoost", '=', margin) << std::endl; +        // can't throw with BOOST_THROW_EXCEPTION(), just use catch_several() +        catch_several(plain_throw<FromBoost>, "plain_throw<FromBoost>"); + +        std::cout << center("FromNeither", '=', margin) << std::endl; +        // can't throw this with BOOST_THROW_EXCEPTION() either +        catch_several(plain_throw<FromNeither>, "plain_throw<FromNeither>"); + +        std::cout << center("const char*", '=', margin) << std::endl; +        // We don't expect BOOST_THROW_EXCEPTION() to throw anything so daft +        // as a const char* or an int, so don't bother with +        // catch_both_several() -- just catch_several(). +        catch_several(throw_char_ptr, "throw_char_ptr"); + +        std::cout << center("int", '=', margin) << std::endl; +        catch_several(throw_int, "throw_int"); +    } +} // namespace tut diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index 785197ba11..9a4bbbd630 100644 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h @@ -35,13 +35,13 @@  #include <tut/tut.hpp>  #include "llerrorcontrol.h" +#include "llexception.h"  #include "stringize.h"  #include <boost/bind.hpp>  #include <boost/noncopyable.hpp>  #include <boost/shared_ptr.hpp>  #include <list>  #include <string> -#include <stdexcept>  // statically reference the function in test.cpp... it's short, we could  // replicate, but better to reuse @@ -67,9 +67,9 @@ struct WrapLLErrs          LLError::restoreSettings(mPriorErrorSettings);      } -    struct FatalException: public std::runtime_error +    struct FatalException: public LLException      { -        FatalException(const std::string& what): std::runtime_error(what) {} +        FatalException(const std::string& what): LLException(what) {}      };      void operator()(const std::string& message) @@ -78,7 +78,7 @@ struct WrapLLErrs          error = message;          // Also throw an appropriate exception since calling code is likely to          // assume that control won't continue beyond LL_ERRS. -        throw FatalException(message); +        LLTHROW(FatalException(message));      }      std::string error; diff --git a/indra/llcrashlogger/llcrashlogger.h b/indra/llcrashlogger/llcrashlogger.h index 8b4afae24a..56e26c23ba 100644 --- a/indra/llcrashlogger/llcrashlogger.h +++ b/indra/llcrashlogger/llcrashlogger.h @@ -57,7 +57,7 @@ public:  	LLSD constructPostData();  	virtual void updateApplication(const std::string& message = LLStringUtil::null);  	virtual bool init(); -	virtual bool mainLoop() = 0; +	virtual bool frame() = 0;  	virtual bool cleanup() = 0;  	void commonCleanup();  	void setUserText(const std::string& text) { mCrashInfo["UserNotes"] = text; } diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp index aad139f570..640eda7b01 100644 --- a/indra/llimage/llpngwrapper.cpp +++ b/indra/llimage/llpngwrapper.cpp @@ -31,6 +31,15 @@  #include "llimage.h"  #include "llpngwrapper.h" +#include "llexception.h" + +namespace { +struct PngError: public LLException +{ +    PngError(png_const_charp msg): LLException(msg) {} +}; +} // anonymous namespace +  // ---------------------------------------------------------------------------  // LLPngWrapper  // --------------------------------------------------------------------------- @@ -75,11 +84,10 @@ BOOL LLPngWrapper::isValidPng(U8* src)  }  // Called by the libpng library when a fatal encoding or decoding error -// occurs.  We simply throw the error message and let our try/catch -// block clean up. +// occurs. We throw PngError and let our try/catch block clean up.  void LLPngWrapper::errorHandler(png_structp png_ptr, png_const_charp msg)  { -	throw msg; +	LLTHROW(PngError(msg));  }  // Called by the libpng library when reading (decoding) the PNG file. We @@ -129,7 +137,7 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf  			this, &errorHandler, NULL);  		if (mReadPngPtr == NULL)  		{ -			throw "Problem creating png read structure"; +			LLTHROW(PngError("Problem creating png read structure"));  		}  		// Allocate/initialize the memory for image information. @@ -187,9 +195,9 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf  		mFinalSize = dataPtr.mOffset;  	} -	catch (png_const_charp msg) +	catch (const PngError& msg)  	{ -		mErrorMessage = msg; +		mErrorMessage = msg.what();  		releaseResources();  		return (FALSE);  	} @@ -288,14 +296,14 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest)  		if (mColorType == -1)  		{ -			throw "Unsupported image: unexpected number of channels"; +			LLTHROW(PngError("Unsupported image: unexpected number of channels"));  		}  		mWritePngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING,  			NULL, &errorHandler, NULL);  		if (!mWritePngPtr)  		{ -			throw "Problem creating png write structure"; +			LLTHROW(PngError("Problem creating png write structure"));  		}  		mWriteInfoPtr = png_create_info_struct(mWritePngPtr); @@ -339,9 +347,9 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest)  		png_write_end(mWritePngPtr, mWriteInfoPtr);  		mFinalSize = dataPtr.mOffset;  	} -	catch (png_const_charp msg) +	catch (const PngError& msg)  	{ -		mErrorMessage = msg; +		mErrorMessage = msg.what();  		releaseResources();  		return (FALSE);  	} diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index 9347e51b85..fe79079db3 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -34,6 +34,15 @@  #include "kdu_block_coding.h" +#include "llexception.h" + +namespace { +struct KDUError: public LLException +{ +    KDUError(const std::string& msg): LLException(msg) {} +}; +} // anonymous namespace +  class kdc_flow_control {  public: @@ -167,7 +176,7 @@ struct LLKDUMessageError : public LLKDUMessage  		// exception if we want to recover from a KDU error.  		if (end_of_message)   		{ -			throw "KDU throwing an exception"; +		LLTHROW(KDUError("LLKDUMessageError::flush()"));  		}  	}  }; @@ -384,9 +393,9 @@ bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco  			mTPosp->x = 0;  		}  	} -	catch (const char* msg) +	catch (const KDUError& msg)  	{ -		base.setLastError(ll_safe_string(msg)); +		base.setLastError(msg.what());  		return false;  	}  	catch (...) @@ -480,9 +489,9 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco  					return false;  				}  			} -			catch (const char* msg) +			catch (const KDUError& msg)  			{ -				base.setLastError(ll_safe_string(msg)); +				base.setLastError(msg.what());  				base.decodeFailed();  				cleanupCodeStream();  				return true; // done @@ -673,9 +682,9 @@ bool LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co  		base.updateData(); // set width, height  		delete[] output_buffer;  	} -	catch(const char* msg) +	catch(const KDUError& msg)  	{ -		base.setLastError(ll_safe_string(msg)); +		base.setLastError(msg.what());  		return false;  	}  	catch( ... ) @@ -697,9 +706,9 @@ bool LLImageJ2CKDU::getMetadata(LLImageJ2C &base)  		setupCodeStream(base, false, MODE_FAST);  		return true;  	} -	catch (const char* msg) +	catch (const KDUError& msg)  	{ -		base.setLastError(ll_safe_string(msg)); +		base.setLastError(msg.what());  		return false;  	}  	catch (...) diff --git a/indra/llmessage/llhttpnode.cpp b/indra/llmessage/llhttpnode.cpp index f235965879..04b34a296c 100644 --- a/indra/llmessage/llhttpnode.cpp +++ b/indra/llmessage/llhttpnode.cpp @@ -31,6 +31,7 @@  #include "llstl.h"  #include "llhttpconstants.h" +#include "llexception.h"  const std::string CONTEXT_HEADERS("headers");  const std::string CONTEXT_PATH("path"); @@ -92,27 +93,28 @@ LLHTTPNode::~LLHTTPNode()  namespace { -	class NotImplemented +	struct NotImplemented: public LLException  	{ +		NotImplemented(): LLException("LLHTTPNode::NotImplemented") {}  	};  }  // virtual  LLSD LLHTTPNode::simpleGet() const  { -	throw NotImplemented(); +	LLTHROW(NotImplemented());  }  // virtual  LLSD LLHTTPNode::simplePut(const LLSD& input) const  { -	throw NotImplemented(); +	LLTHROW(NotImplemented());  }  // virtual  LLSD LLHTTPNode::simplePost(const LLSD& input) const  { -	throw NotImplemented(); +	LLTHROW(NotImplemented());  } @@ -172,7 +174,7 @@ void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) cons  // virtual  LLSD LLHTTPNode::simpleDel(const LLSD&) const  { -	throw NotImplemented(); +	LLTHROW(NotImplemented());  }  // virtual diff --git a/indra/llmessage/tests/commtest.h b/indra/llmessage/tests/commtest.h index 0d149b5258..7c8f27bbd2 100644 --- a/indra/llmessage/tests/commtest.h +++ b/indra/llmessage/tests/commtest.h @@ -33,15 +33,15 @@  #include "llevents.h"  #include "llsd.h"  #include "llhost.h" +#include "llexception.h"  #include "stringize.h"  #include <map>  #include <string> -#include <stdexcept>  #include <boost/lexical_cast.hpp> -struct CommtestError: public std::runtime_error +struct CommtestError: public LLException  { -    CommtestError(const std::string& what): std::runtime_error(what) {} +    CommtestError(const std::string& what): LLException(what) {}  };  static bool query_verbose() @@ -68,7 +68,7 @@ static int query_port(const std::string& var)      const char* cport = getenv(var.c_str());      if (! cport)      { -        throw CommtestError(STRINGIZE("missing environment variable" << var)); +        LLTHROW(CommtestError(STRINGIZE("missing environment variable" << var)));      }      // This will throw, too, if the value of PORT isn't numeric.      int port(boost::lexical_cast<int>(cport)); diff --git a/indra/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h index 2aff90ca1e..5eb739393f 100644 --- a/indra/llmessage/tests/networkio.h +++ b/indra/llmessage/tests/networkio.h @@ -34,6 +34,7 @@  #include "llares.h"  #include "llpumpio.h"  #include "llhttpclient.h" +#include "llexception.h"  /*****************************************************************************  *   NetworkIO @@ -51,7 +52,7 @@ public:          ll_init_apr();          if (! gAPRPoolp)          { -            throw std::runtime_error("Can't initialize APR"); +            LLTHROW(LLException("Can't initialize APR"));          }          // Create IO Pump to use for HTTP Requests. @@ -59,7 +60,7 @@ public:          LLHTTPClient::setPump(*mServicePump);          if (ll_init_ares() == NULL || !gAres->isInitialized())          { -            throw std::runtime_error("Can't start DNS resolver"); +            LLTHROW(LLException("Can't start DNS resolver"));          }          // You can interrupt pump() without waiting the full timeout duration diff --git a/indra/llwindow/llappdelegate-objc.h b/indra/llwindow/llappdelegate-objc.h index faa5d3abb7..6daf1ac55b 100644 --- a/indra/llwindow/llappdelegate-objc.h +++ b/indra/llwindow/llappdelegate-objc.h @@ -41,7 +41,7 @@  @property (retain) NSString *currentInputLanguage; -- (void) mainLoop; +- (void) oneFrame;  - (void) showInputWindow:(bool)show withEvent:(NSEvent*)textEvent;  - (void) languageUpdated;  - (bool) romanScript; diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index c22f3382fb..b06cd2c184 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -69,7 +69,7 @@ typedef const NativeKeyEventData * NSKeyEventRef;  // These are defined in llappviewermacosx.cpp.  bool initViewer();  void handleQuit(); -bool runMainLoop(); +bool pumpMainLoop();  void initMainLoop();  void cleanupViewer();  void handleUrl(const char* url); diff --git a/indra/mac_crash_logger/llcrashloggermac.cpp b/indra/mac_crash_logger/llcrashloggermac.cpp index 3149fad6e8..ec3616e26a 100644 --- a/indra/mac_crash_logger/llcrashloggermac.cpp +++ b/indra/mac_crash_logger/llcrashloggermac.cpp @@ -64,7 +64,7 @@ void LLCrashLoggerMac::gatherPlatformSpecificFiles()  {  } -bool LLCrashLoggerMac::mainLoop() +bool LLCrashLoggerMac::frame()  {      if (mCrashBehavior == CRASH_BEHAVIOR_ALWAYS_SEND) diff --git a/indra/mac_crash_logger/llcrashloggermac.h b/indra/mac_crash_logger/llcrashloggermac.h index 6d8f63ecac..05ef8c9f53 100644 --- a/indra/mac_crash_logger/llcrashloggermac.h +++ b/indra/mac_crash_logger/llcrashloggermac.h @@ -37,7 +37,7 @@ public:  	LLCrashLoggerMac(void);  	~LLCrashLoggerMac(void);  	virtual bool init(); -	virtual bool mainLoop(); +	virtual bool frame();  	virtual bool cleanup();  	virtual void gatherPlatformSpecificFiles();  }; diff --git a/indra/mac_crash_logger/mac_crash_logger.cpp b/indra/mac_crash_logger/mac_crash_logger.cpp index 95d4e65207..54e41a1954 100644 --- a/indra/mac_crash_logger/mac_crash_logger.cpp +++ b/indra/mac_crash_logger/mac_crash_logger.cpp @@ -49,7 +49,7 @@ int main(int argc, char **argv)      {  //        return NSApplicationMain(argc, (const char **)argv);      } -	app.mainLoop(); +	app.frame();  	app.cleanup();  	LL_INFOS() << "Crash reporter finished normally." << LL_ENDL; diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp index 49291ea564..dbcae57de7 100644 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -534,7 +534,7 @@ LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url,  		// somewhat clumsy, as we may run into errors that do not map directly to curl  		// error codes.  Should be refactored with login refactoring, perhaps.  		result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_CACERT); -		result.setMessage(cert_exception.getMessage()); +		result.setMessage(cert_exception.what());  		LLPointer<LLCertificate> cert = cert_exception.getCert();  		cert->ref(); // adding an extra ref here  		result.setErrorData(cert.get()); @@ -544,7 +544,7 @@ LLCore::HttpStatus LLAppCoreHttp::sslVerify(const std::string &url,  	catch (LLCertException &cert_exception)  	{  		result = LLCore::HttpStatus(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SSL_PEER_CERTIFICATE); -		result.setMessage(cert_exception.getMessage()); +		result.setMessage(cert_exception.what());  		LLPointer<LLCertificate> cert = cert_exception.getCert();  		cert->ref(); // adding an extra ref here  		result.setErrorData(cert.get()); diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index 549df80fa1..be8877328d 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -48,16 +48,19 @@  - (void) applicationDidFinishLaunching:(NSNotification *)notification  {  	frameTimer = nil; -	 +  	[self languageUpdated]; -	 +  	if (initViewer())  	{ -		frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(mainLoop) userInfo:nil repeats:YES]; +		// Set up recurring calls to oneFrame (repeating timer with timeout 0) +		// until applicationShouldTerminate. +		frameTimer = [NSTimer scheduledTimerWithTimeInterval:0.0 target:self +							  selector:@selector(oneFrame) userInfo:nil repeats:YES];  	} else {  		handleQuit();  	} -	 +  	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(languageUpdated) name:@"NSTextInputContextKeyboardSelectionDidChangeNotification" object:nil];   //   [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleGetURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL]; @@ -96,22 +99,29 @@  - (NSApplicationDelegateReply) applicationShouldTerminate:(NSApplication *)sender  { -	if (!runMainLoop()) +	// run one frame to assess state +	if (!pumpMainLoop())  	{ +		// pumpMainLoop() returns true when done, false if it wants to be +		// called again. Since it returned false, do not yet cancel +		// frameTimer.  		handleQuit();  		return NSTerminateCancel;  	} else { +		// pumpMainLoop() returned true: it's done. Okay, done with frameTimer.  		[frameTimer release];  		cleanupViewer();  		return NSTerminateNow;  	}  } -- (void) mainLoop +- (void) oneFrame  { -	bool appExiting = runMainLoop(); +	bool appExiting = pumpMainLoop();  	if (appExiting)  	{ +		// Once pumpMainLoop() reports that we're done, cancel frameTimer: +		// stop the repetitive calls.  		[frameTimer release];  		[[NSApplication sharedApplication] terminate:self];  	} diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 6bc1f67e32..766c807169 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -122,6 +122,7 @@  #include "llleap.h"  #include "stringize.h"  #include "llcoros.h" +#include "llexception.h"  #if !LL_LINUX  #include "cef/llceflib.h"  #endif @@ -231,7 +232,6 @@  #include "llcoproceduremanager.h"  #include "llviewereventrecorder.h" -  // *FIX: These extern globals should be cleaned up.  // The globals either represent state/config/resource-storage of either   // this app, or another 'component' of the viewer. App globals should be  @@ -769,9 +769,6 @@ bool LLAppViewer::init()  	//  	// Start of the application  	// -#ifdef LL_DARWIN -	mMainLoopInitialized = false; -#endif  	// initialize LLWearableType translation bridge.  	// Memory will be cleaned up in ::cleanupClass() @@ -1220,6 +1217,23 @@ bool LLAppViewer::init()          boost::bind(&LLControlGroup::getU32, boost::ref(gSavedSettings), _1),          boost::bind(&LLControlGroup::declareU32, boost::ref(gSavedSettings), _1, _2, _3, LLControlVariable::PERSIST_ALWAYS)); +	/*----------------------------------------------------------------------*/ +	// nat 2016-06-29 moved the following here from the former mainLoop(). +	mMainloopTimeout = new LLWatchdogTimeout(); + +	// Create IO Pump to use for HTTP Requests. +	gServicePump = new LLPumpIO(gAPRPoolp); + +	// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated. + +	LLVoiceChannel::initClass(); +	LLVoiceClient::getInstance()->init(gServicePump); +	LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true); + +	joystick = LLViewerJoystick::getInstance(); +	joystick->setNeedsReset(true); +	/*----------------------------------------------------------------------*/ +  	return true;  } @@ -1294,297 +1308,255 @@ static LLTrace::BlockTimerStatHandle FTM_AGENT_UPDATE("Update");  // externally visible timers  LLTrace::BlockTimerStatHandle FTM_FRAME("Frame"); -bool LLAppViewer::mainLoop() +bool LLAppViewer::frame()  { -#ifdef LL_DARWIN -	if (!mMainLoopInitialized) -#endif -	{ -        LL_INFOS() << "Entering main_loop" << LL_ENDL; -		mMainloopTimeout = new LLWatchdogTimeout(); -		 -		//------------------------------------------- -		// Run main loop until time to quit -		//------------------------------------------- -		 -		// Create IO Pump to use for HTTP Requests. -		gServicePump = new LLPumpIO(gAPRPoolp); -		 -		// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated. -		 -		LLVoiceChannel::initClass(); -		LLVoiceClient::getInstance()->init(gServicePump); -		LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLFloaterIMContainer::onCurrentChannelChanged, _1), true); -		 -		joystick = LLViewerJoystick::getInstance(); -		joystick->setNeedsReset(true); -		 -#ifdef LL_DARWIN -		// Ensure that this section of code never gets called again on OS X. -		mMainLoopInitialized = true; -#endif -	} -	// As we do not (yet) send data on the mainloop LLEventPump that varies -	// with each frame, no need to instantiate a new LLSD event object each -	// time. Obviously, if that changes, just instantiate the LLSD at the -	// point of posting. -	  	LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); -	 -    LLSD newFrame; -	 +	LLSD newFrame; +  	LLTimer frameTimer,idleTimer;  	LLTimer debugTime; -	 +  	//LLPrivateMemoryPoolTester::getInstance()->run(false) ;  	//LLPrivateMemoryPoolTester::getInstance()->run(true) ;  	//LLPrivateMemoryPoolTester::destroy() ; -	// Handle messages -#ifdef LL_DARWIN -	if (!LLApp::isExiting()) -#else -	while (!LLApp::isExiting()) -#endif +	LL_RECORD_BLOCK_TIME(FTM_FRAME); +	LLTrace::BlockTimer::processTimes(); +	LLTrace::get_frame_recording().nextPeriod(); +	LLTrace::BlockTimer::logStats(); + +	LLTrace::get_thread_recorder()->pullFromChildren(); + +	//clear call stack records +	LL_CLEAR_CALLSTACKS(); + +	//check memory availability information +	checkMemory() ; + +	try  	{ -		LL_RECORD_BLOCK_TIME(FTM_FRAME); -		LLTrace::BlockTimer::processTimes(); -		LLTrace::get_frame_recording().nextPeriod(); -		LLTrace::BlockTimer::logStats(); +		pingMainloopTimeout("Main:MiscNativeWindowEvents"); + +		if (gViewerWindow) +		{ +			LL_RECORD_BLOCK_TIME(FTM_MESSAGES); +			gViewerWindow->getWindow()->processMiscNativeEvents(); +		} -		LLTrace::get_thread_recorder()->pullFromChildren(); +		pingMainloopTimeout("Main:GatherInput"); -		//clear call stack records -		LL_CLEAR_CALLSTACKS(); +		if (gViewerWindow) +		{ +			LL_RECORD_BLOCK_TIME(FTM_MESSAGES); +			if (!restoreErrorTrap()) +			{ +				LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL; +			} -		//check memory availability information -		checkMemory() ; +			gViewerWindow->getWindow()->gatherInput(); +		} + +#if 1 && !LL_RELEASE_FOR_DOWNLOAD +		// once per second debug info +		if (debugTime.getElapsedTimeF32() > 1.f) +		{ +			debugTime.reset(); +		} -		try +#endif +		//memory leaking simulation +		LLFloaterMemLeak* mem_leak_instance = +			LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); +		if(mem_leak_instance)  		{ -			pingMainloopTimeout("Main:MiscNativeWindowEvents"); +			mem_leak_instance->idle() ;				 +		}							 + +		// canonical per-frame event +		mainloop.post(newFrame); -			if (gViewerWindow) +		if (!LLApp::isExiting()) +		{ +			pingMainloopTimeout("Main:JoystickKeyboard"); + +			// Scan keyboard for movement keys.  Command keys and typing +			// are handled by windows callbacks.  Don't do this until we're +			// done initializing.  JC +			if ((gHeadlessClient || gViewerWindow->getWindow()->getVisible()) +				&& gViewerWindow->getActive() +				&& !gViewerWindow->getWindow()->getMinimized() +				&& LLStartUp::getStartupState() == STATE_STARTED +				&& (gHeadlessClient || !gViewerWindow->getShowProgress()) +				&& !gFocusMgr.focusLocked())  			{ -				LL_RECORD_BLOCK_TIME(FTM_MESSAGES); -				gViewerWindow->getWindow()->processMiscNativeEvents(); +				joystick->scanJoystick(); +				gKeyboard->scanKeyboard();  			} -		 -			pingMainloopTimeout("Main:GatherInput"); -			 -			if (gViewerWindow) + +			// Update state based on messages, user input, object idle.  			{ -				LL_RECORD_BLOCK_TIME(FTM_MESSAGES); -				if (!restoreErrorTrap()) -				{ -					LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL; -				} +				pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds! +				 +				LL_RECORD_BLOCK_TIME(FTM_IDLE); +				idle(); -				gViewerWindow->getWindow()->gatherInput(); +				resumeMainloopTimeout();  			} -#if 1 && !LL_RELEASE_FOR_DOWNLOAD -			// once per second debug info -			if (debugTime.getElapsedTimeF32() > 1.f) +			if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))  			{ -				debugTime.reset(); +				pauseMainloopTimeout(); +				saveFinalSnapshot(); +				disconnectViewer(); +				resumeMainloopTimeout();  			} -			 -#endif -			//memory leaking simulation -			LLFloaterMemLeak* mem_leak_instance = -				LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); -			if(mem_leak_instance) -			{ -				mem_leak_instance->idle() ;				 -			}							 -            // canonical per-frame event -            mainloop.post(newFrame); - -			if (!LLApp::isExiting()) +			// Render scene. +			// *TODO: Should we run display() even during gHeadlessClient?  DK 2011-02-18 +			if (!LLApp::isExiting() && !gHeadlessClient)  			{ -				pingMainloopTimeout("Main:JoystickKeyboard"); -				 -				// Scan keyboard for movement keys.  Command keys and typing -				// are handled by windows callbacks.  Don't do this until we're -				// done initializing.  JC -				if ((gHeadlessClient || gViewerWindow->getWindow()->getVisible()) -					&& gViewerWindow->getActive() -					&& !gViewerWindow->getWindow()->getMinimized() -					&& LLStartUp::getStartupState() == STATE_STARTED -					&& (gHeadlessClient || !gViewerWindow->getShowProgress()) -					&& !gFocusMgr.focusLocked()) -				{ -					joystick->scanJoystick(); -					gKeyboard->scanKeyboard(); -				} +				pingMainloopTimeout("Main:Display"); +				gGLActive = TRUE; +				display(); +				pingMainloopTimeout("Main:Snapshot"); +				LLFloaterSnapshot::update(); // take snapshots +				gGLActive = FALSE; +			} +		} -				// Update state based on messages, user input, object idle. -				{ -					pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds! -					 -					LL_RECORD_BLOCK_TIME(FTM_IDLE); -					idle(); +		pingMainloopTimeout("Main:Sleep"); -					resumeMainloopTimeout(); -				} -  -				if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED)) -				{ -					pauseMainloopTimeout(); -					saveFinalSnapshot(); -					disconnectViewer(); -					resumeMainloopTimeout(); -				} +		pauseMainloopTimeout(); -				// Render scene. -				// *TODO: Should we run display() even during gHeadlessClient?  DK 2011-02-18 -				if (!LLApp::isExiting() && !gHeadlessClient) +		// Sleep and run background threads +		{ +			LL_RECORD_BLOCK_TIME(FTM_SLEEP); +			 +			// yield some time to the os based on command line option +			if(mYieldTime >= 0) +			{ +				LL_RECORD_BLOCK_TIME(FTM_YIELD); +				ms_sleep(mYieldTime); +			} + +			// yield cooperatively when not running as foreground window +			if (   (gViewerWindow && !gViewerWindow->getWindow()->getVisible()) +					|| !gFocusMgr.getAppHasFocus()) +			{ +				// Sleep if we're not rendering, or the window is minimized. +				S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000); +				// don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads +				// of equal priority on Windows +				if (milliseconds_to_sleep > 0)  				{ -					pingMainloopTimeout("Main:Display"); -					gGLActive = TRUE; -					display(); -					pingMainloopTimeout("Main:Snapshot"); -					LLFloaterSnapshot::update(); // take snapshots -					gGLActive = FALSE; +					ms_sleep(milliseconds_to_sleep); +					// also pause worker threads during this wait period +					LLAppViewer::getTextureCache()->pause(); +					LLAppViewer::getImageDecodeThread()->pause();  				}  			} - -			pingMainloopTimeout("Main:Sleep"); -			pauseMainloopTimeout(); +			if (mRandomizeFramerate) +			{ +				ms_sleep(rand() % 200); +			} -			// Sleep and run background threads +			if (mPeriodicSlowFrame +				&& (gFrameCount % 10 == 0))  			{ -				LL_RECORD_BLOCK_TIME(FTM_SLEEP); -				 -				// yield some time to the os based on command line option -				if(mYieldTime >= 0) -				{ -					LL_RECORD_BLOCK_TIME(FTM_YIELD); -					ms_sleep(mYieldTime); -				} +				LL_INFOS() << "Periodic slow frame - sleeping 500 ms" << LL_ENDL; +				ms_sleep(500); +			} + +			const F64Milliseconds max_idle_time = llmin(.005f*10.f*(F32Milliseconds)gFrameTimeSeconds, F32Milliseconds(5)); // 5 ms a second +			idleTimer.reset(); +			S32 total_work_pending = 0; +			S32 total_io_pending = 0;	 +			while(1) +			{ +				S32 work_pending = 0; +				S32 io_pending = 0; +				F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f); + +				work_pending += updateTextureThreads(max_time); -				// yield cooperatively when not running as foreground window -				if (   (gViewerWindow && !gViewerWindow->getWindow()->getVisible()) -						|| !gFocusMgr.getAppHasFocus())  				{ -					// Sleep if we're not rendering, or the window is minimized. -					S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000); -					// don't sleep when BackgroundYieldTime set to 0, since this will still yield to other threads -					// of equal priority on Windows -					if (milliseconds_to_sleep > 0) -					{ -						ms_sleep(milliseconds_to_sleep); -						// also pause worker threads during this wait period -						LLAppViewer::getTextureCache()->pause(); -						LLAppViewer::getImageDecodeThread()->pause(); -					} +					LL_RECORD_BLOCK_TIME(FTM_VFS); + 					io_pending += LLVFSThread::updateClass(1);  				} -				 -				if (mRandomizeFramerate)  				{ -					ms_sleep(rand() % 200); +					LL_RECORD_BLOCK_TIME(FTM_LFS); + 					io_pending += LLLFSThread::updateClass(1);  				} -				if (mPeriodicSlowFrame -					&& (gFrameCount % 10 == 0)) +				if (io_pending > 1000)  				{ -					LL_INFOS() << "Periodic slow frame - sleeping 500 ms" << LL_ENDL; -					ms_sleep(500); +					ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up  				} -				const F64Milliseconds max_idle_time = llmin(.005f*10.f*(F32Milliseconds)gFrameTimeSeconds, F32Milliseconds(5)); // 5 ms a second -				idleTimer.reset(); -				S32 total_work_pending = 0; -				S32 total_io_pending = 0;	 -				while(1) -				{ -					S32 work_pending = 0; -					S32 io_pending = 0; -					F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f); - -					work_pending += updateTextureThreads(max_time); - -					{ -						LL_RECORD_BLOCK_TIME(FTM_VFS); -	 					io_pending += LLVFSThread::updateClass(1); -					} -					{ -						LL_RECORD_BLOCK_TIME(FTM_LFS); -	 					io_pending += LLLFSThread::updateClass(1); -					} - -					if (io_pending > 1000) -					{ -						ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up -					} - -					total_work_pending += work_pending ; -					total_io_pending += io_pending ; -					 -					if (!work_pending || idleTimer.getElapsedTimeF64() >= max_idle_time) -					{ -						break; -					} -				} -				gMeshRepo.update() ; +				total_work_pending += work_pending ; +				total_io_pending += io_pending ; -				if(!total_work_pending) //pause texture fetching threads if nothing to process. -				{ -					LLAppViewer::getTextureCache()->pause(); -					LLAppViewer::getImageDecodeThread()->pause(); -					LLAppViewer::getTextureFetch()->pause();  -				} -				if(!total_io_pending) //pause file threads if nothing to process. -				{ -					LLVFSThread::sLocal->pause();  -					LLLFSThread::sLocal->pause();  -				}									 - -				//texture fetching debugger -				if(LLTextureFetchDebugger::isEnabled()) +				if (!work_pending || idleTimer.getElapsedTimeF64() >= max_idle_time)  				{ -					LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance = -						LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger"); -					if(tex_fetch_debugger_instance) -					{ -						tex_fetch_debugger_instance->idle() ;				 -					} +					break;  				} +			} +			gMeshRepo.update() ; +			 +			if(!total_work_pending) //pause texture fetching threads if nothing to process. +			{ +				LLAppViewer::getTextureCache()->pause(); +				LLAppViewer::getImageDecodeThread()->pause(); +				LLAppViewer::getTextureFetch()->pause();  +			} +			if(!total_io_pending) //pause file threads if nothing to process. +			{ +				LLVFSThread::sLocal->pause();  +				LLLFSThread::sLocal->pause();  +			}									 -				if ((LLStartUp::getStartupState() >= STATE_CLEANUP) && -					(frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD)) +			//texture fetching debugger +			if(LLTextureFetchDebugger::isEnabled()) +			{ +				LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance = +					LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger"); +				if(tex_fetch_debugger_instance)  				{ -					gFrameStalls++; +					tex_fetch_debugger_instance->idle() ;				  				} -				frameTimer.reset(); - -				resumeMainloopTimeout(); -	 -				pingMainloopTimeout("Main:End"); -			}	 -		} -		catch(std::bad_alloc) -		{			 -			LLMemory::logMemoryInfo(TRUE) ; +			} -			//stop memory leaking simulation -			LLFloaterMemLeak* mem_leak_instance = -				LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); -			if(mem_leak_instance) +			if ((LLStartUp::getStartupState() >= STATE_CLEANUP) && +				(frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD))  			{ -				mem_leak_instance->stop() ;				 -				LL_WARNS() << "Bad memory allocation in LLAppViewer::mainLoop()!" << LL_ENDL ; +				gFrameStalls++;  			} -			else -			{ -				//output possible call stacks to log file. -				LLError::LLCallStacks::print() ; +			frameTimer.reset(); -				LL_ERRS() << "Bad memory allocation in LLAppViewer::mainLoop()!" << LL_ENDL ; -			} +			resumeMainloopTimeout(); + +			pingMainloopTimeout("Main:End"); +		}	 +	} +	catch(std::bad_alloc) +	{			 +		LLMemory::logMemoryInfo(TRUE) ; + +		//stop memory leaking simulation +		LLFloaterMemLeak* mem_leak_instance = +			LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking"); +		if(mem_leak_instance) +		{ +			mem_leak_instance->stop() ;				 +			LL_WARNS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL ; +		} +		else +		{ +			//output possible call stacks to log file. +			LLError::LLCallStacks::print() ; + +			LL_ERRS() << "Bad memory allocation in LLAppViewer::frame()!" << LL_ENDL ;  		}  	} @@ -1618,7 +1590,7 @@ bool LLAppViewer::mainLoop()  		LL_INFOS() << "Exiting main_loop" << LL_ENDL;  	} -	return LLApp::isExiting(); +	return ! LLApp::isRunning();  }  S32 LLAppViewer::updateTextureThreads(F32 max_time) @@ -5546,8 +5518,7 @@ void LLAppViewer::forceErrorInfiniteLoop()  void LLAppViewer::forceErrorSoftwareException()  {     	LL_WARNS() << "Forcing a deliberate exception" << LL_ENDL; -    // *FIX: Any way to insure it won't be handled? -    throw;  +    LLTHROW(LLException("User selected Force Software Exception"));  }  void LLAppViewer::forceErrorDriverCrash() diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index b5e674bd7b..f7c1bb58b4 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -79,7 +79,7 @@ public:  	//  	virtual bool init();			// Override to do application initialization  	virtual bool cleanup();			// Override to do application cleanup -	virtual bool mainLoop(); // Override for the application main loop.  Needs to at least gracefully notice the QUITTING state and exit. +	virtual bool frame(); // Override for application body logic  	// Application control  	void flushVFSIO(); // waits for vfs transfers to complete @@ -283,7 +283,6 @@ private:  	std::string mSerialNumber;  	bool mPurgeCache;      bool mPurgeOnExit; -	bool mMainLoopInitialized;  	LLViewerJoystick* joystick;  	bool mSavedFinalSnapshot; diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index f5742b29cf..6f32aab851 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -95,10 +95,8 @@ int main( int argc, char **argv )  	}  		// Run the application main loop -	if(!LLApp::isQuitting())  -	{ -		viewer_app_ptr->mainLoop(); -	} +	while (! viewer_app_ptr->frame())  +	{}  	if (!LLApp::isError())  	{ diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index ca219fda59..4fe1e31668 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -117,12 +117,17 @@ void handleQuit()  	LLAppViewer::instance()->userQuit();  } -bool runMainLoop() +// This function is called pumpMainLoop() rather than runMainLoop() because +// it passes control to the viewer's main-loop logic for a single frame. Like +// LLAppViewer::frame(), it returns 'true' when it's done. Until then, it +// expects to be called again by the timer in LLAppDelegate +// (llappdelegate-objc.mm). +bool pumpMainLoop()  {  	bool ret = LLApp::isQuitting();  	if (!ret && gViewerAppPtr != NULL)  	{ -		ret = gViewerAppPtr->mainLoop(); +		ret = gViewerAppPtr->frame();  	} else {  		ret = true;  	} diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 4786f83bfd..a7f248ab5a 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -317,10 +317,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,  	}  	// Run the application main loop -	if(!LLApp::isQuitting())  -	{ -		viewer_app_ptr->mainLoop(); -	} +	while (! viewer_app_ptr->frame())  +	{}  	if (!LLApp::isError())  	{ diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp index 1819fc74ee..90a5483dc9 100644 --- a/indra/newview/llcommandlineparser.cpp +++ b/indra/newview/llcommandlineparser.cpp @@ -26,6 +26,7 @@  #include "llviewerprecompiledheaders.h"  #include "llcommandlineparser.h" +#include "llexception.h"  // *NOTE: The boost::lexical_cast generates   // the warning C4701(local used with out assignment) in VC7.1. @@ -50,6 +51,7 @@  #include "llsdserialize.h"  #include "llerror.h"  #include "stringize.h" +#include "llexception.h"  #include <string>  #include <set>  #include <iostream> @@ -98,14 +100,14 @@ namespace      bool gPastLastOption = false;  } -class LLCLPError : public std::logic_error { +class LLCLPError : public LLException {  public: -    LLCLPError(const std::string& what) : std::logic_error(what) {} +    LLCLPError(const std::string& what) : LLException(what) {}  }; -class LLCLPLastOption : public std::logic_error { +class LLCLPLastOption : public LLException {  public: -    LLCLPLastOption(const std::string& what) : std::logic_error(what) {} +    LLCLPLastOption(const std::string& what) : LLException(what) {}  };  class LLCLPValue : public po::value_semantic_codecvt_helper<char>  @@ -202,17 +204,17 @@ protected:      {          if(gPastLastOption)          { -            throw(LLCLPLastOption("Don't parse no more!")); +            LLTHROW(LLCLPLastOption("Don't parse no more!"));          }          // Error checks. Needed?          if (!value_store.empty() && !is_composing())           { -            throw(LLCLPError("Non composing value with multiple occurences.")); +            LLTHROW(LLCLPError("Non composing value with multiple occurences."));          }          if (new_tokens.size() < min_tokens() || new_tokens.size() > max_tokens())          { -            throw(LLCLPError("Illegal number of tokens specified.")); +            LLTHROW(LLCLPError("Illegal number of tokens specified."));          }          if(value_store.empty()) @@ -466,7 +468,7 @@ onevalue(const std::string& option,      {          // What does it mean when the user specifies a command-line switch          // that requires a value, but omits the value? Complain. -        throw LLCLPError(STRINGIZE("No value specified for --" << option << "!")); +        LLTHROW(LLCLPError(STRINGIZE("No value specified for --" << option << "!")));      }      else if (value.size() > 1)      { @@ -484,9 +486,9 @@ void badvalue(const std::string& option,      // If the user passes an unusable value for a command-line switch, it      // seems like a really bad idea to just ignore it, even with a log      // warning. -    throw LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option -                               << "' for variable '" << varname << "' of type " << type -                               << ": '" << value << "'")); +    LLTHROW(LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option +                                 << "' for variable '" << varname << "' of type " << type +                                 << ": '" << value << "'")));  }  template <typename T> diff --git a/indra/newview/llsecapi.cpp b/indra/newview/llsecapi.cpp index 4f9f83b6f2..933f7bb16e 100644 --- a/indra/newview/llsecapi.cpp +++ b/indra/newview/llsecapi.cpp @@ -29,6 +29,7 @@  #include "llviewerprecompiledheaders.h"  #include "llsecapi.h"  #include "llsechandler_basic.h" +#include "llexception.h"  #include <openssl/evp.h>  #include <openssl/err.h>  #include <map> @@ -64,12 +65,12 @@ void initializeSecHandler()  		}  		catch (LLProtectedDataException e)  		{ -			exception_msg = e.getMessage(); +			exception_msg = e.what();  		}  	}  	if (!exception_msg.empty())  // an exception was thrown.  	{ -		throw LLProtectedDataException(exception_msg.c_str()); +		LLTHROW(LLProtectedDataException(exception_msg));  	}  } diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h index 6fe3ee31cf..6af5a28fa5 100644 --- a/indra/newview/llsecapi.h +++ b/indra/newview/llsecapi.h @@ -32,6 +32,7 @@  #include <openssl/x509.h>  #include <ostream>  #include "llpointer.h" +#include "llexception.h"  #ifdef LL_WINDOWS  #pragma warning(disable:4250) @@ -116,17 +117,13 @@ -class LLProtectedDataException +struct LLProtectedDataException: public LLException  { -public: -	LLProtectedDataException(const char *msg)  +	LLProtectedDataException(const std::string& msg): +		LLException(msg)  	{ -		LL_WARNS("SECAPI") << "Protected Data Error: " << (std::string)msg << LL_ENDL; -		mMsg = (std::string)msg; +		LL_WARNS("SECAPI") << "Protected Data Error: " << msg << LL_ENDL;  	} -	std::string getMessage() { return mMsg; } -protected: -	std::string mMsg;  };  // class LLCertificate @@ -334,22 +331,21 @@ std::ostream& operator <<(std::ostream& s, const LLCredential& cred);  // All error handling is via exceptions. -class LLCertException +class LLCertException: public LLException  {  public: -	LLCertException(LLPointer<LLCertificate> cert, const char* msg) +	LLCertException(LLPointer<LLCertificate> cert, const std::string& msg): +		LLException(msg)  	{  		mCert = cert; -		LL_WARNS("SECAPI") << "Certificate Error: " << (std::string)msg << LL_ENDL; -		mMsg = (std::string)msg; +		LL_WARNS("SECAPI") << "Certificate Error: " << msg << LL_ENDL;  	} -	LLPointer<LLCertificate> getCert() { return mCert; } -	std::string getMessage() { return mMsg; } +	virtual ~LLCertException() throw() {} +	LLPointer<LLCertificate> getCert() const { return mCert; }  protected:  	LLPointer<LLCertificate> mCert; -	std::string mMsg;  };  class LLInvalidCertificate : public LLCertException @@ -358,6 +354,7 @@ public:  	LLInvalidCertificate(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalid")  	{  	} +	virtual ~LLInvalidCertificate() throw() {}  protected:  }; @@ -367,6 +364,7 @@ public:  	LLCertValidationTrustException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertUntrusted")  	{  	} +	virtual ~LLCertValidationTrustException() throw() {}  protected:  }; @@ -378,7 +376,7 @@ public:  	{  		mHostname = hostname;  	} -	 +	virtual ~LLCertValidationHostnameException() throw() {}  	std::string getHostname() { return mHostname; }  protected:  	std::string mHostname; @@ -392,6 +390,7 @@ public:  	{  		mTime = current_time;  	} +	virtual ~LLCertValidationExpirationException() throw() {}  	LLDate GetTime() { return mTime; }  protected:  	LLDate mTime; @@ -403,6 +402,7 @@ public:  	LLCertKeyUsageValidationException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertKeyUsage")  	{  	} +	virtual ~LLCertKeyUsageValidationException() throw() {}  protected:  }; @@ -412,6 +412,7 @@ public:  	LLCertBasicConstraintsValidationException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertBasicConstraints")  	{  	} +	virtual ~LLCertBasicConstraintsValidationException() throw() {}  protected:  }; @@ -421,6 +422,7 @@ public:  	LLCertValidationInvalidSignatureException(LLPointer<LLCertificate> cert) : LLCertException(cert, "CertInvalidSignature")  	{  	} +	virtual ~LLCertValidationInvalidSignatureException() throw() {}  protected:  }; diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index 40516f9bbb..183a625382 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -35,6 +35,7 @@  #include "llfile.h"  #include "lldir.h"  #include "llviewercontrol.h" +#include "llexception.h"  #include <vector>  #include <ios>  #include <openssl/ossl_typ.h> @@ -72,14 +73,14 @@ LLBasicCertificate::LLBasicCertificate(const std::string& pem_cert)  	if(pem_bio == NULL)  	{  		LL_WARNS("SECAPI") << "Could not allocate an openssl memory BIO." << LL_ENDL; -		throw LLInvalidCertificate(this); +		LLTHROW(LLInvalidCertificate(this));  	}  	mCert = NULL;  	PEM_read_bio_X509(pem_bio, &mCert, 0, NULL);  	BIO_free(pem_bio);  	if (!mCert)  	{ -		throw LLInvalidCertificate(this); +		LLTHROW(LLInvalidCertificate(this));  	}  } @@ -88,7 +89,7 @@ LLBasicCertificate::LLBasicCertificate(X509* pCert)  {  	if (!pCert || !pCert->cert_info)  	{ -		throw LLInvalidCertificate(this); +		LLTHROW(LLInvalidCertificate(this));  	}	  	mCert = X509_dup(pCert);  } @@ -873,22 +874,22 @@ void _validateCert(int validation_policy,  	// check basic properties exist in the cert  	if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info.has(CERT_SUBJECT_NAME_STRING))  	{ -		throw LLCertException(cert, "Cert doesn't have a Subject Name");				 +		LLTHROW(LLCertException(cert, "Cert doesn't have a Subject Name"));  	}  	if(!current_cert_info.has(CERT_ISSUER_NAME_STRING))  	{ -		throw LLCertException(cert, "Cert doesn't have an Issuer Name");				 +		LLTHROW(LLCertException(cert, "Cert doesn't have an Issuer Name"));  	}  	// check basic properties exist in the cert  	if(!current_cert_info.has(CERT_VALID_FROM) || !current_cert_info.has(CERT_VALID_TO))  	{ -		throw LLCertException(cert, "Cert doesn't have an expiration period");				 +		LLTHROW(LLCertException(cert, "Cert doesn't have an expiration period"));  	}  	if (!current_cert_info.has(CERT_SHA1_DIGEST))  	{ -		throw LLCertException(cert, "No SHA1 digest"); +		LLTHROW(LLCertException(cert, "No SHA1 digest"));  	}  	if (validation_policy & VALIDATION_POLICY_TIME) @@ -903,7 +904,7 @@ void _validateCert(int validation_policy,  		if((validation_date < current_cert_info[CERT_VALID_FROM].asDate()) ||  		   (validation_date > current_cert_info[CERT_VALID_TO].asDate()))  		{ -			throw LLCertValidationExpirationException(cert, validation_date); +			LLTHROW(LLCertValidationExpirationException(cert, validation_date));  		}  	}  	if (validation_policy & VALIDATION_POLICY_SSL_KU) @@ -914,14 +915,14 @@ void _validateCert(int validation_policy,  			!(_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE],   									  LLSD((std::string)CERT_KU_KEY_ENCIPHERMENT)))))  		{ -			throw LLCertKeyUsageValidationException(cert); +			LLTHROW(LLCertKeyUsageValidationException(cert));  		}  		// only validate EKU if the cert has it  		if(current_cert_info.has(CERT_EXTENDED_KEY_USAGE) && current_cert_info[CERT_EXTENDED_KEY_USAGE].isArray() &&	     		   (!_LLSDArrayIncludesValue(current_cert_info[CERT_EXTENDED_KEY_USAGE],   									LLSD((std::string)CERT_EKU_SERVER_AUTH))))  		{ -			throw LLCertKeyUsageValidationException(cert);			 +			LLTHROW(LLCertKeyUsageValidationException(cert));  		}  	}  	if (validation_policy & VALIDATION_POLICY_CA_KU) @@ -930,7 +931,7 @@ void _validateCert(int validation_policy,  			(!_LLSDArrayIncludesValue(current_cert_info[CERT_KEY_USAGE],   									   (std::string)CERT_KU_CERT_SIGN)))  			{ -				throw LLCertKeyUsageValidationException(cert);						 +				LLTHROW(LLCertKeyUsageValidationException(cert));  			}  	} @@ -942,13 +943,13 @@ void _validateCert(int validation_policy,  		if(!current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_CA) ||  		   !current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_CA])  		{ -				throw LLCertBasicConstraintsValidationException(cert); +				LLTHROW(LLCertBasicConstraintsValidationException(cert));  		}  		if (current_cert_info[CERT_BASIC_CONSTRAINTS].has(CERT_BASIC_CONSTRAINTS_PATHLEN) &&  			((current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger() != 0) &&  			 (depth > current_cert_info[CERT_BASIC_CONSTRAINTS][CERT_BASIC_CONSTRAINTS_PATHLEN].asInteger())))  		{ -			throw LLCertBasicConstraintsValidationException(cert);					 +			LLTHROW(LLCertBasicConstraintsValidationException(cert));  		}  	}  } @@ -1018,7 +1019,7 @@ void LLBasicCertificateStore::validate(int validation_policy,  	if(cert_chain->size() < 1)  	{ -		throw LLCertException(NULL, "No certs in chain"); +		LLTHROW(LLCertException(NULL, "No certs in chain"));  	}  	iterator current_cert = cert_chain->begin();  	LLSD 	current_cert_info; @@ -1033,11 +1034,11 @@ void LLBasicCertificateStore::validate(int validation_policy,  		(*current_cert)->getLLSD(current_cert_info);  		if(!validation_params.has(CERT_HOSTNAME))  		{ -			throw LLCertException((*current_cert), "No hostname passed in for validation");			 +			LLTHROW(LLCertException((*current_cert), "No hostname passed in for validation"));  		}  		if(!current_cert_info.has(CERT_SUBJECT_NAME) || !current_cert_info[CERT_SUBJECT_NAME].has(CERT_NAME_CN))  		{ -			throw LLInvalidCertificate((*current_cert));				 +			LLTHROW(LLInvalidCertificate((*current_cert)));  		}  		LL_DEBUGS("SECAPI") << "Validating the hostname " << validation_params[CERT_HOSTNAME].asString() <<  @@ -1054,7 +1055,7 @@ void LLBasicCertificateStore::validate(int validation_policy,  	X509* cert_x509 = (*current_cert)->getOpenSSLX509();  	if(!cert_x509)  	{ -		throw LLInvalidCertificate((*current_cert));			 +		LLTHROW(LLInvalidCertificate((*current_cert)));  	}  	std::string sha1_hash((const char *)cert_x509->sha1_hash, SHA_DIGEST_LENGTH);  	X509_free( cert_x509 ); @@ -1075,7 +1076,7 @@ void LLBasicCertificateStore::validate(int validation_policy,  			if((validation_date < cache_entry->second.first) ||  			   (validation_date > cache_entry->second.second))  			{ -				throw LLCertValidationExpirationException((*current_cert), validation_date); +				LLTHROW(LLCertValidationExpirationException((*current_cert), validation_date));  			}  		}  		// successfully found in cache @@ -1107,7 +1108,7 @@ void LLBasicCertificateStore::validate(int validation_policy,  			if(!_verify_signature((*current_cert),  								  previous_cert))  			{ -			   throw LLCertValidationInvalidSignatureException(previous_cert); +			   LLTHROW(LLCertValidationInvalidSignatureException(previous_cert));  			}  		}  		_validateCert(local_validation_policy, @@ -1156,7 +1157,7 @@ void LLBasicCertificateStore::validate(int validation_policy,  			if(!_verify_signature((*found_store_cert),  								  (*current_cert)))  			{ -				throw LLCertValidationInvalidSignatureException(*current_cert); +				LLTHROW(LLCertValidationInvalidSignatureException(*current_cert));  			}			  			// successfully validated.  			mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time);		 @@ -1173,7 +1174,7 @@ void LLBasicCertificateStore::validate(int validation_policy,  	if (validation_policy & VALIDATION_POLICY_TRUSTED)  	{  		// we reached the end without finding a trusted cert. -		throw LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1]); +		LLTHROW(LLCertValidationTrustException((*cert_chain)[cert_chain->size()-1]));  	}  	mTrustedCertCache[sha1_hash] = std::pair<LLDate, LLDate>(from_time, to_time);	 @@ -1261,7 +1262,7 @@ void LLSecAPIBasicHandler::_readProtectedData()  		protected_data_stream.read((char *)salt, STORE_SALT_SIZE);  		if (protected_data_stream.gcount() < STORE_SALT_SIZE)  		{ -			throw LLProtectedDataException("Config file too short."); +			LLTHROW(LLProtectedDataException("Config file too short."));  		}  		cipher.decrypt(salt, STORE_SALT_SIZE);		 @@ -1301,7 +1302,7 @@ void LLSecAPIBasicHandler::_readProtectedData()  		if (parser->parse(parse_stream, mProtectedDataMap,   						  LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE)  		{ -			throw LLProtectedDataException("Config file cannot be decrypted."); +			LLTHROW(LLProtectedDataException("Config file cannot be decrypted."));  		}  	}  } @@ -1372,7 +1373,7 @@ void LLSecAPIBasicHandler::_writeProtectedData()  		// EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData()  		// Decided throwing an exception here was overkill until we figure out why this happens -		//throw LLProtectedDataException("Error writing Protected Data Store"); +		//LLTHROW(LLProtectedDataException("Error writing Protected Data Store"));  	}      try @@ -1387,7 +1388,7 @@ void LLSecAPIBasicHandler::_writeProtectedData()              // EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData()              // Decided throwing an exception here was overkill until we figure out why this happens -            //throw LLProtectedDataException("Could not overwrite protected data store"); +            //LLTHROW(LLProtectedDataException("Could not overwrite protected data store"));          }  	}  	catch (...) @@ -1401,7 +1402,7 @@ void LLSecAPIBasicHandler::_writeProtectedData()  		//crash in LLSecAPIBasicHandler::_writeProtectedData()  		// Decided throwing an exception here was overkill until we figure out why this happens -		//throw LLProtectedDataException("Error writing Protected Data Store"); +		//LLTHROW(LLProtectedDataException("Error writing Protected Data Store"));  	}  } diff --git a/indra/test/llapp_tut.cpp b/indra/test/llapp_tut.cpp index aa5c0672e6..98e714a497 100644 --- a/indra/test/llapp_tut.cpp +++ b/indra/test/llapp_tut.cpp @@ -41,7 +41,7 @@ namespace tut  		public:  			virtual bool init() { return true; }  			virtual bool cleanup() { return true; } -			virtual bool mainLoop() { return true; } +			virtual bool frame() { return true; }  		};  		LLTestApp* mApp;  		application() diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 382689afa0..04e0395c50 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -27,7 +27,7 @@  #include "llupdatedownloader.h"  #include "httpcommon.h" -#include <stdexcept> +#include "llexception.h"  #include <boost/format.hpp>  #include <boost/lexical_cast.hpp>  #include <curl/curl.h> @@ -85,11 +85,11 @@ private:  namespace {  	class DownloadError: -		public std::runtime_error +		public LLException  	{  	public:  		DownloadError(const char * message): -			std::runtime_error(message) +			LLException(message)  		{  			; // No op.  		} @@ -467,7 +467,7 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u  	if(!mCurl)  	{ -		throw DownloadError("failed to initialize curl"); +		LLTHROW(DownloadError("failed to initialize curl"));  	}      throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_NOSIGNAL, true));  	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_FOLLOWLOCATION, true)); @@ -508,7 +508,7 @@ void LLUpdateDownloader::Implementation::resumeDownloading(size_t startByte)  	mHeaderList = curl_slist_append(mHeaderList, rangeHeaderFormat.str().c_str());  	if(mHeaderList == 0)  	{ -		throw DownloadError("cannot add Range header"); +		LLTHROW(DownloadError("cannot add Range header"));  	}  	throwOnCurlError(curl_easy_setopt(mCurl.get(), CURLOPT_HTTPHEADER, mHeaderList)); @@ -524,7 +524,7 @@ void LLUpdateDownloader::Implementation::startDownloading(LLURI const & uri, std  	mDownloadData["hash"] = hash;  	mDownloadData["current_version"] = ll_get_version();  	LLSD path = uri.pathArray(); -	if(path.size() == 0) throw DownloadError("no file path"); +	if(path.size() == 0) LLTHROW(DownloadError("no file path"));  	std::string fileName = path[path.size() - 1].asString();  	std::string filePath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, fileName);  	mDownloadData["path"] = filePath; @@ -547,9 +547,9 @@ void LLUpdateDownloader::Implementation::throwOnCurlError(CURLcode code)  	if(code != CURLE_OK) {  		const char * errorString = curl_easy_strerror(code);  		if(errorString != 0) { -			throw DownloadError(curl_easy_strerror(code)); +			LLTHROW(DownloadError(curl_easy_strerror(code)));  		} else { -			throw DownloadError("unknown curl error"); +			LLTHROW(DownloadError("unknown curl error"));  		}  	} else {  		; // No op. diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp index a0e2c0b362..1c7629da23 100644 --- a/indra/viewer_components/updater/llupdateinstaller.cpp +++ b/indra/viewer_components/updater/llupdateinstaller.cpp @@ -30,23 +30,25 @@  #include "llupdateinstaller.h"  #include "lldir.h"   #include "llsd.h" +#include "llexception.h"  #if defined(LL_WINDOWS)  #pragma warning(disable: 4702)      // disable 'unreachable code' so we can use lexical_cast (really!).  #endif  #include <boost/lexical_cast.hpp> -  namespace { -	class RelocateError {}; -	 -	 +	struct RelocateError: public LLException +	{ +		RelocateError(): LLException("llupdateinstaller: RelocateError") {} +	}; +  	std::string copy_to_temp(std::string const & path)  	{  		std::string scriptFile = gDirUtilp->getBaseFileName(path);  		std::string newPath = gDirUtilp->getExpandedFilename(LL_PATH_TEMP, scriptFile);  		apr_status_t status = apr_file_copy(path.c_str(), newPath.c_str(), APR_FILE_SOURCE_PERMS, gAPRPoolp); -		if(status != APR_SUCCESS) throw RelocateError(); +		if(status != APR_SUCCESS) LLTHROW(RelocateError());  		return newPath;  	} diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index 788955a1b2..1665e41e70 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -32,6 +32,7 @@  #include "lltimer.h"  #include "llupdatechecker.h"  #include "llupdateinstaller.h" +#include "llexception.h"  #include <boost/scoped_ptr.hpp>  #include <boost/weak_ptr.hpp> @@ -190,8 +191,8 @@ void LLUpdaterServiceImpl::initialize(const std::string&  channel,  {  	if(mIsChecking || mIsDownloading)  	{ -		throw LLUpdaterService::UsageError("LLUpdaterService::initialize call " -										   "while updater is running."); +		LLTHROW(LLUpdaterService::UsageError("LLUpdaterService::initialize call " +											  "while updater is running."));  	}  	mChannel = channel; @@ -222,8 +223,8 @@ void LLUpdaterServiceImpl::startChecking(bool install_if_ready)  {  	if(mChannel.empty() || mVersion.empty())  	{ -		throw LLUpdaterService::UsageError("Set params before call to " -			"LLUpdaterService::startCheck()."); +		LLTHROW(LLUpdaterService::UsageError("Set params before call to " +											 "LLUpdaterService::startCheck()."));  	}  	mIsChecking = true; diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h index 95bbe1695c..78e8c6b290 100644 --- a/indra/viewer_components/updater/llupdaterservice.h +++ b/indra/viewer_components/updater/llupdaterservice.h @@ -29,16 +29,17 @@  #include <boost/shared_ptr.hpp>  #include <boost/function.hpp>  #include "llhasheduniqueid.h" +#include "llexception.h"  class LLUpdaterServiceImpl;  class LLUpdaterService  {  public: -	class UsageError: public std::runtime_error +	class UsageError: public LLException  	{  	public: -		UsageError(const std::string& msg) : std::runtime_error(msg) {} +		UsageError(const std::string& msg) : LLException(msg) {}  	};  	// Name of the event pump through which update events will be delivered. diff --git a/indra/win_crash_logger/llcrashloggerwindows.cpp b/indra/win_crash_logger/llcrashloggerwindows.cpp index 23c29e6b18..167acf6ac7 100644 --- a/indra/win_crash_logger/llcrashloggerwindows.cpp +++ b/indra/win_crash_logger/llcrashloggerwindows.cpp @@ -454,7 +454,7 @@ void LLCrashLoggerWindows::gatherPlatformSpecificFiles()  	//mDebugLog["DisplayDeviceInfo"] = gDXHardware.getDisplayInfo();  //Not initialized.  } -bool LLCrashLoggerWindows::mainLoop() +bool LLCrashLoggerWindows::frame()  {	  	LL_INFOS() << "CrashSubmitBehavior is " << mCrashBehavior << LL_ENDL; @@ -503,14 +503,14 @@ bool LLCrashLoggerWindows::mainLoop()  			TranslateMessage(&msg);  			DispatchMessage(&msg);  		} -		return msg.wParam; +		return true; // msg.wParam;  	}  	else  	{  		LL_WARNS() << "Unknown crash behavior " << mCrashBehavior << LL_ENDL; -		return 1; +		return true; // 1;  	} -	return 0; +	return true; // 0;  }  void LLCrashLoggerWindows::updateApplication(const std::string& message) diff --git a/indra/win_crash_logger/llcrashloggerwindows.h b/indra/win_crash_logger/llcrashloggerwindows.h index 1812e2737e..f89b8708dc 100644 --- a/indra/win_crash_logger/llcrashloggerwindows.h +++ b/indra/win_crash_logger/llcrashloggerwindows.h @@ -46,7 +46,7 @@ public:  	static LLCrashLoggerWindows* sInstance;   	virtual bool init(); -	virtual bool mainLoop(); +	virtual bool frame();  	virtual void updateApplication(const std::string& message = LLStringUtil::null);  	virtual bool cleanup();  	virtual void gatherPlatformSpecificFiles(); diff --git a/indra/win_crash_logger/win_crash_logger.cpp b/indra/win_crash_logger/win_crash_logger.cpp index 366edd894b..7466dbb766 100644 --- a/indra/win_crash_logger/win_crash_logger.cpp +++ b/indra/win_crash_logger/win_crash_logger.cpp @@ -52,7 +52,7 @@ int APIENTRY WinMain(HINSTANCE hInstance,  	}  	app.processingLoop(); -	app.mainLoop(); +	app.frame();  	app.cleanup();  	LL_INFOS() << "Crash reporter finished normally." << LL_ENDL;  	return 0; | 
