Automated merge with ssh://bitbucket.org/lindenlab/viewer-release

master
Nat Goodspeed 2016-08-17 11:41:12 -04:00
commit e72bdc9bc5
53 changed files with 927 additions and 473 deletions

View File

@ -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>

View File

@ -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;

View File

@ -114,7 +114,7 @@ void LLCrashLoggerLinux::gatherPlatformSpecificFiles()
{
}
bool LLCrashLoggerLinux::mainLoop()
bool LLCrashLoggerLinux::frame()
{
bool send_logs = true;
if(CRASH_BEHAVIOR_ASK == getCrashBehavior())

View File

@ -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();

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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) {}
};
/**

View File

@ -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).

View File

@ -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() {}

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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) */

View File

@ -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.

View File

@ -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();

View File

@ -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;
}

View File

@ -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) {}
};
/**

View File

@ -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;
}

View File

@ -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.
}

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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; }

View File

@ -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);
}

View File

@ -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 (...)

View File

@ -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

View File

@ -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));

View File

@ -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

View File

@ -41,7 +41,7 @@
@property (retain) NSString *currentInputLanguage;
- (void) mainLoop;
- (void) oneFrame;
- (void) showInputWindow:(bool)show withEvent:(NSEvent*)textEvent;
- (void) languageUpdated;
- (bool) romanScript;

View File

@ -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);

View File

@ -64,7 +64,7 @@ void LLCrashLoggerMac::gatherPlatformSpecificFiles()
{
}
bool LLCrashLoggerMac::mainLoop()
bool LLCrashLoggerMac::frame()
{
if (mCrashBehavior == CRASH_BEHAVIOR_ALWAYS_SEND)

View File

@ -37,7 +37,7 @@ public:
LLCrashLoggerMac(void);
~LLCrashLoggerMac(void);
virtual bool init();
virtual bool mainLoop();
virtual bool frame();
virtual bool cleanup();
virtual void gatherPlatformSpecificFiles();
};

View File

@ -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;

View File

@ -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());

View File

@ -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];
}

View File

@ -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");
LLTrace::get_thread_recorder()->pullFromChildren();
//clear call stack records
LL_CLEAR_CALLSTACKS();
//check memory availability information
checkMemory() ;
try
if (gViewerWindow)
{
pingMainloopTimeout("Main:MiscNativeWindowEvents");
LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
gViewerWindow->getWindow()->processMiscNativeEvents();
}
if (gViewerWindow)
{
LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
gViewerWindow->getWindow()->processMiscNativeEvents();
}
pingMainloopTimeout("Main:GatherInput");
if (gViewerWindow)
{
LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
if (!restoreErrorTrap())
{
LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL;
}
pingMainloopTimeout("Main:GatherInput");
gViewerWindow->getWindow()->gatherInput();
if (gViewerWindow)
{
LL_RECORD_BLOCK_TIME(FTM_MESSAGES);
if (!restoreErrorTrap())
{
LL_WARNS() << " Someone took over my signal/exception handler (post messagehandling)!" << LL_ENDL;
}
gViewerWindow->getWindow()->gatherInput();
}
#if 1 && !LL_RELEASE_FOR_DOWNLOAD
// once per second debug info
if (debugTime.getElapsedTimeF32() > 1.f)
{
debugTime.reset();
}
// once per second debug info
if (debugTime.getElapsedTimeF32() > 1.f)
{
debugTime.reset();
}
#endif
//memory leaking simulation
LLFloaterMemLeak* mem_leak_instance =
LLFloaterReg::findTypedInstance<LLFloaterMemLeak>("mem_leaking");
if(mem_leak_instance)
//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())
{
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())
{
mem_leak_instance->idle() ;
}
// canonical per-frame event
mainloop.post(newFrame);
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())
{
joystick->scanJoystick();
gKeyboard->scanKeyboard();
}
// 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();
resumeMainloopTimeout();
}
if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
{
pauseMainloopTimeout();
saveFinalSnapshot();
disconnectViewer();
resumeMainloopTimeout();
}
// Render scene.
// *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18
if (!LLApp::isExiting() && !gHeadlessClient)
{
pingMainloopTimeout("Main:Display");
gGLActive = TRUE;
display();
pingMainloopTimeout("Main:Snapshot");
LLFloaterSnapshot::update(); // take snapshots
gGLActive = FALSE;
}
joystick->scanJoystick();
gKeyboard->scanKeyboard();
}
pingMainloopTimeout("Main:Sleep");
pauseMainloopTimeout();
// Sleep and run background threads
// Update state based on messages, user input, object idle.
{
LL_RECORD_BLOCK_TIME(FTM_SLEEP);
pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
// 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)
{
ms_sleep(milliseconds_to_sleep);
// also pause worker threads during this wait period
LLAppViewer::getTextureCache()->pause();
LLAppViewer::getImageDecodeThread()->pause();
}
}
if (mRandomizeFramerate)
{
ms_sleep(rand() % 200);
}
if (mPeriodicSlowFrame
&& (gFrameCount % 10 == 0))
{
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);
{
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() ;
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())
{
LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance =
LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger");
if(tex_fetch_debugger_instance)
{
tex_fetch_debugger_instance->idle() ;
}
}
if ((LLStartUp::getStartupState() >= STATE_CLEANUP) &&
(frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD))
{
gFrameStalls++;
}
frameTimer.reset();
LL_RECORD_BLOCK_TIME(FTM_IDLE);
idle();
resumeMainloopTimeout();
pingMainloopTimeout("Main:End");
}
}
if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
{
pauseMainloopTimeout();
saveFinalSnapshot();
disconnectViewer();
resumeMainloopTimeout();
}
// Render scene.
// *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18
if (!LLApp::isExiting() && !gHeadlessClient)
{
pingMainloopTimeout("Main:Display");
gGLActive = TRUE;
display();
pingMainloopTimeout("Main:Snapshot");
LLFloaterSnapshot::update(); // take snapshots
gGLActive = FALSE;
}
}
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::mainLoop()!" << LL_ENDL ;
}
else
{
//output possible call stacks to log file.
LLError::LLCallStacks::print() ;
pingMainloopTimeout("Main:Sleep");
LL_ERRS() << "Bad memory allocation in LLAppViewer::mainLoop()!" << LL_ENDL ;
pauseMainloopTimeout();
// 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)
{
ms_sleep(milliseconds_to_sleep);
// also pause worker threads during this wait period
LLAppViewer::getTextureCache()->pause();
LLAppViewer::getImageDecodeThread()->pause();
}
}
if (mRandomizeFramerate)
{
ms_sleep(rand() % 200);
}
if (mPeriodicSlowFrame
&& (gFrameCount % 10 == 0))
{
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);
{
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() ;
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())
{
LLFloaterTextureFetchDebugger* tex_fetch_debugger_instance =
LLFloaterReg::findTypedInstance<LLFloaterTextureFetchDebugger>("tex_fetch_debugger");
if(tex_fetch_debugger_instance)
{
tex_fetch_debugger_instance->idle() ;
}
}
if ((LLStartUp::getStartupState() >= STATE_CLEANUP) &&
(frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD))
{
gFrameStalls++;
}
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)
{
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()

View File

@ -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;

View File

@ -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())
{

View File

@ -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;
}

View File

@ -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())
{

View File

@ -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>

View File

@ -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));
}
}

View File

@ -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:
};

View File

@ -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"));
}
}

View File

@ -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()

View File

@ -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.

View File

@ -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;
}

View File

@ -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;

View File

@ -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.

View File

@ -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)

View File

@ -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();

View File

@ -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;