Error integration: error::Flag as subclass of State. Wrapped throw

This commit is contained in:
Fischlurch 2010-02-13 20:56:41 +01:00
parent acd0671390
commit 90d311dc1d
5 changed files with 134 additions and 69 deletions

View file

@ -192,7 +192,6 @@ namespace backend {
lumiera_thread_join (thread_); lumiera_thread_join (thread_);
thread_ = 0; thread_ = 0;
TODO("check this, is error::State approbiate or do we want Runtime as thrown by throwOnError()");
if (errorInOtherThread) if (errorInOtherThread)
throw lumiera::error::State ("Thread terminated with error:", errorInOtherThread); throw lumiera::error::State ("Thread terminated with error:", errorInOtherThread);
} }

View file

@ -2,7 +2,7 @@
ERROR.hpp - Lumiera Exception Interface ERROR.hpp - Lumiera Exception Interface
Copyright (C) Lumiera.org Copyright (C) Lumiera.org
2008, Hermann Vosseler <Ichthyostega@web.de> 2008-2010 Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as modify it under the terms of the GNU General Public License as
@ -49,9 +49,9 @@ namespace lumiera {
class Error : public std::exception class Error : public std::exception
{ {
public: public:
Error (string description="", const char* id=LUMIERA_ERROR_EXCEPTION) throw(); Error (string description="", const char* const id=LUMIERA_ERROR_EXCEPTION) throw();
Error (std::exception const& cause, Error (std::exception const& cause,
string description="", const char* id=LUMIERA_ERROR_EXCEPTION) throw(); string description="", const char* const id=LUMIERA_ERROR_EXCEPTION) throw();
Error (const Error&) throw(); Error (const Error&) throw();
virtual ~Error () throw() {}; virtual ~Error () throw() {};
@ -97,8 +97,7 @@ namespace lumiera {
/* === Exception Sub-categories === */ /* === Exception Sub-categories === */
namespace error namespace error {
{
/** global function for handling unknown exceptions /** global function for handling unknown exceptions
* encountered at functions declaring not to throw * encountered at functions declaring not to throw
@ -117,6 +116,7 @@ namespace lumiera {
LUMIERA_ERROR_DECLARE (FATAL ); ///< unable to cope with, internal logic floundered LUMIERA_ERROR_DECLARE (FATAL ); ///< unable to cope with, internal logic floundered
LUMIERA_ERROR_DECLARE (CONFIG ); ///< execution aborted due to misconfiguration LUMIERA_ERROR_DECLARE (CONFIG ); ///< execution aborted due to misconfiguration
LUMIERA_ERROR_DECLARE (STATE ); ///< unforeseen internal state LUMIERA_ERROR_DECLARE (STATE ); ///< unforeseen internal state
LUMIERA_ERROR_DECLARE (FLAG ); ///< non-cleared lumiera errorstate from C code
LUMIERA_ERROR_DECLARE (INVALID ); ///< invalid input or parameters encountered LUMIERA_ERROR_DECLARE (INVALID ); ///< invalid input or parameters encountered
LUMIERA_ERROR_DECLARE (EXTERNAL ); ///< failure in external service the application relies on LUMIERA_ERROR_DECLARE (EXTERNAL ); ///< failure in external service the application relies on
LUMIERA_ERROR_DECLARE (ASSERTION); ///< assertion failure LUMIERA_ERROR_DECLARE (ASSERTION); ///< assertion failure
@ -125,7 +125,6 @@ namespace lumiera {
LUMIERA_ERROR_DECLARE (WRONG_TYPE); ///< runtime type mismatch LUMIERA_ERROR_DECLARE (WRONG_TYPE); ///< runtime type mismatch
LUMIERA_ERROR_DECLARE (ITER_EXHAUST); ///< end of sequence reached LUMIERA_ERROR_DECLARE (ITER_EXHAUST); ///< end of sequence reached
LUMIERA_ERROR_DECLARE (BOTTOM_VALUE); ///< invalid or NIL value LUMIERA_ERROR_DECLARE (BOTTOM_VALUE); ///< invalid or NIL value
LUMIERA_ERROR_DECLARE (RUNTIME); ///< generic runtime error, will be overridden by id
/** Macro for creating derived exception classes properly /** Macro for creating derived exception classes properly
@ -143,7 +142,7 @@ namespace lumiera {
const char* id=_ID_) throw() \ const char* id=_ID_) throw() \
: PARENT (description, id) {} \ : PARENT (description, id) {} \
\ \
CLASS (std::exception& cause, \ CLASS (std::exception const& cause, \
std::string description="", \ std::string description="", \
const char* id=_ID_) throw() \ const char* id=_ID_) throw() \
: PARENT (cause, description, id) {} \ : PARENT (cause, description, id) {} \
@ -154,30 +153,59 @@ namespace lumiera {
LUMIERA_EXCEPTION_DECLARE (Fatal, Logic, LUMIERA_ERROR_FATAL); LUMIERA_EXCEPTION_DECLARE (Fatal, Logic, LUMIERA_ERROR_FATAL);
LUMIERA_EXCEPTION_DECLARE (Config, Error, LUMIERA_ERROR_CONFIG); LUMIERA_EXCEPTION_DECLARE (Config, Error, LUMIERA_ERROR_CONFIG);
LUMIERA_EXCEPTION_DECLARE (State, Error, LUMIERA_ERROR_STATE); LUMIERA_EXCEPTION_DECLARE (State, Error, LUMIERA_ERROR_STATE);
LUMIERA_EXCEPTION_DECLARE (Flag, State, LUMIERA_ERROR_FLAG);
LUMIERA_EXCEPTION_DECLARE (Invalid, Error, LUMIERA_ERROR_INVALID); LUMIERA_EXCEPTION_DECLARE (Invalid, Error, LUMIERA_ERROR_INVALID);
LUMIERA_EXCEPTION_DECLARE (External, Error, LUMIERA_ERROR_EXTERNAL); LUMIERA_EXCEPTION_DECLARE (External, Error, LUMIERA_ERROR_EXTERNAL);
LUMIERA_EXCEPTION_DECLARE (Runtime, Error, LUMIERA_ERROR_RUNTIME);
/** install our own handler for undeclared exceptions. Will be /** install our own handler for undeclared exceptions. Will be
* called automatically ON_BASIC_INIT when linking exception.cpp */ * called automatically ON_BASIC_INIT when linking exception.cpp */
void install_unexpectedException_handler (); void install_unexpectedException_handler ();
/** @return error detail-info if currently set, a default message else */
const char* detailInfo ();
} // namespace error } // namespace error
/** /**
* Throw a 'Runtime' error which wraps an existing lumiera error * Check the lumiera error state, which maybe was set by C-code.
* no-op when no error is pending. Does not clear the error state. * @throw Errorflag exception to signal an detected lumiera error
* @note specific error code and information is enclosed in
* the raised exception; the error state is \em not cleared.
*/ */
static inline void throwOnError() inline void
throwOnError()
{ {
lumiera_err err = lumiera_error_peek(); if (lumiera_err errorFlag =lumiera_error())
if (err)
{ {
const char* extra = lumiera_error_extra(); throw error::Flag( error::detailInfo()
throw error::Runtime(extra?extra:"", err); , errorFlag);
} } } //causes the error state to be set
/** Check the lumiera error state and throw a specific exception
* in case a non-cleared errorflag is detected. No-op else.
* @throw instance of the lumiera::Error subclass provided as
* template parameter, containing an lumiera::error::Flag
* as root cause to denote the detected error-flag state.
*/
template<class EX>
inline void
maybeThrow(string description)
{
if (lumiera_err errorFlag =lumiera_error())
{
throw EX (error::Flag( error::detailInfo()
, errorFlag)
,description);
} }
template<class EX>
inline void
maybeThrow()
{
maybeThrow<EX>("");
} }

View file

@ -34,6 +34,11 @@ using std::exception;
namespace lumiera { namespace lumiera {
typedef const char* CStr;
typedef const char* const CCStr;
namespace error { namespace error {
/** the message shown to the user per default /** the message shown to the user per default
@ -48,18 +53,27 @@ namespace lumiera {
+ typeid(*exception_obj).name() + ")"; + typeid(*exception_obj).name() + ")";
} }
inline const char* inline CStr
default_or_given (const char* id) default_or_given (CCStr id)
{ {
return id? id : LUMIERA_ERROR_STATE; return id? id : LUMIERA_ERROR_STATE;
} }
CStr
detailInfo ()
{
CCStr detailinfo = lumiera_error_extra();
return isnil (detailinfo)? "Lumiera errorstate detected"
: detailinfo;
}
/* constants to be used as error IDs */ /* constants to be used as error IDs */
LUMIERA_ERROR_DEFINE (LOGIC , "internal logic broken"); LUMIERA_ERROR_DEFINE (LOGIC , "internal logic broken");
LUMIERA_ERROR_DEFINE (FATAL , "floundered"); LUMIERA_ERROR_DEFINE (FATAL , "floundered");
LUMIERA_ERROR_DEFINE (CONFIG , "misconfiguration"); LUMIERA_ERROR_DEFINE (CONFIG , "misconfiguration");
LUMIERA_ERROR_DEFINE (STATE , "unforeseen state"); LUMIERA_ERROR_DEFINE (STATE , "unforeseen state");
LUMIERA_ERROR_DEFINE (FLAG , "non-cleared lumiera errorstate");
LUMIERA_ERROR_DEFINE (INVALID , "invalid input or parameters"); LUMIERA_ERROR_DEFINE (INVALID , "invalid input or parameters");
LUMIERA_ERROR_DEFINE (EXTERNAL , "failure in external service"); LUMIERA_ERROR_DEFINE (EXTERNAL , "failure in external service");
LUMIERA_ERROR_DEFINE (ASSERTION, "assertion failure"); LUMIERA_ERROR_DEFINE (ASSERTION, "assertion failure");
@ -78,7 +92,7 @@ namespace lumiera {
/** @note we set the C-style errorstate as a side effect */ /** @note we set the C-style errorstate as a side effect */
Error::Error (string description, const char* id) throw() Error::Error (string description, CCStr id) throw()
: std::exception (), : std::exception (),
id_ (error::default_or_given (id)), id_ (error::default_or_given (id)),
msg_ (error::default_usermsg (this)), msg_ (error::default_usermsg (this)),
@ -90,7 +104,7 @@ namespace lumiera {
Error::Error (std::exception const& cause, Error::Error (std::exception const& cause,
string description, const char* id) throw() string description, CCStr id) throw()
: std::exception (), : std::exception (),
id_ (error::default_or_given (id)), id_ (error::default_or_given (id)),
msg_ (error::default_usermsg (this)), msg_ (error::default_usermsg (this)),
@ -117,7 +131,7 @@ namespace lumiera {
* If a root cause can be obtained, this will be included in the * If a root cause can be obtained, this will be included in the
* generated output as well. * generated output as well.
*/ */
const char* CStr
Error::what() const throw() Error::what() const throw()
{ {
if (isnil (this->what_)) if (isnil (this->what_))
@ -160,13 +174,13 @@ namespace lumiera {
void lumiera_unexpectedException () throw() void lumiera_unexpectedException () throw()
{ {
const char* is_halted CCStr is_halted
= "### Lumiera halted due to an unexpected Error ###"; = "### Lumiera halted due to an unexpected Error ###";
std::cerr << "\n" << is_halted << "\n\n"; std::cerr << "\n" << is_halted << "\n\n";
ERROR (NOBUG_ON, "%s", is_halted); ERROR (NOBUG_ON, "%s", is_halted);
if (const char * errorstate = lumiera_error ()) if (CCStr errorstate = lumiera_error ())
ERROR (NOBUG_ON, "last registered error was....\n%s", errorstate); ERROR (NOBUG_ON, "last registered error was....\n%s", errorstate);
std::terminate(); std::terminate();

View file

@ -205,7 +205,9 @@ out: intermediate handler caught: LUMIERA_ERROR_EXTERNAL:failure in external ser
out: caught lumiera::Error: LUMIERA_ERROR_STATE:unforeseen state -- caused by: LUMIERA_ERROR_EXTERNAL:failure in external service \(test-7\). out: caught lumiera::Error: LUMIERA_ERROR_STATE:unforeseen state -- caused by: LUMIERA_ERROR_EXTERNAL:failure in external service \(test-7\).
out: intermediate handler caught: LUMIERA_ERROR_EXTERNAL:failure in external service \(test-8\).....will rethrow as error::State out: intermediate handler caught: LUMIERA_ERROR_EXTERNAL:failure in external service \(test-8\).....will rethrow as error::State
out: 2nd intermediate handler caught: LUMIERA_ERROR_STATE:unforeseen state -- caused by: LUMIERA_ERROR_EXTERNAL:failure in external service \(test-8\).....will rethrow as error::Config out: 2nd intermediate handler caught: LUMIERA_ERROR_STATE:unforeseen state -- caused by: LUMIERA_ERROR_EXTERNAL:failure in external service \(test-8\).....will rethrow as error::Config
out: caught lumiera::Error: LUMIERA_ERROR_CONFIG:misconfiguration -- caused by: LUMIERA_ERROR_EXTERNAL:failure in external service \(test-8\). out: caught lumiera::Error: LUMIERA_ERROR_CONFIG:misconfiguration -- caused by: LUMIERA_ERROR_EXTERNAL:failure in external service \(test-8\)\.
out: caught lumiera::Error: LUMIERA_ERROR_LIFE_AND_UNIVERSE:and everything\? \(what is the answer\?\)\.
out: caught error::Logic: LUMIERA_ERROR_LOGIC:internal logic broken \(the big bang\). -- caused by: LUMIERA_ERROR_LIFE_AND_UNIVERSE:and everything\? \(what is the answer\?\)\.
END END

View file

@ -83,6 +83,7 @@ namespace lumiera {
catcher (&test::doubleNestedTh,"test-8"); catcher (&test::doubleNestedTh,"test-8");
checkErrorIntegration(); checkErrorIntegration();
checkErrorFlagPropagation();
checkRootCauseChaining(); checkRootCauseChaining();
} }
@ -153,6 +154,27 @@ namespace lumiera {
ASSERT (!lumiera_error ()); ASSERT (!lumiera_error ());
} }
void detectErrorflag (string) { throwOnError(); }
void detectErrorflagChained (string msg) { maybeThrow<error::Logic>(msg); }
/** @test verify throwing of Exceptions
* based on a non-cleared C error flag
*/
void checkErrorFlagPropagation()
{
lumiera_error_set(LUMIERA_ERROR_LIFE_AND_UNIVERSE, "what is the answer?");
ASSERT (lumiera_error_peek());
catcher (&test::detectErrorflag, "");
ASSERT (LUMIERA_ERROR_LIFE_AND_UNIVERSE == lumiera_error_peek());
catcher (&test::detectErrorflagChained, "the big bang");
ASSERT (LUMIERA_ERROR_LIFE_AND_UNIVERSE == lumiera_error());
}
/** @test the chaining of lumiera::Exception objects /** @test the chaining of lumiera::Exception objects
* and the retrieval of the original root cause. * and the retrieval of the original root cause.
*/ */