Exception classes

Classes

class  senf::ExceptionMixin
 Generic extensible exception mixin. More...
 
class  senf::Exception
 Extensible exception base-class. More...
 
class  senf::WrapException< BaseException >
 Wrapper for standard non-senf exceptions. More...
 
class  senf::SystemException
 Exception handling standard UNIX errors (errno) More...
 

Macros

#define SENF_WRAP_EXC(Ex)
 Wrap a non-senf exception. More...
 

Detailed Description

All exceptions in senf are derived from senf::Exception. This class adds the possibility to extend the exception description while it is processed. The functionality is provided by a mixin class senf::ExceptionMixin:

try {
// Some code which might raise an arbitrary senf exception
}
catch (senf::ExceptionMixin & e) {
e << "\handling user " << user;
throw;
}
This will add the user information to any %senf exception thrown. The Exception is however not a
stream. If you need to do more extensive formating, either use an intermediate string-stream or
use <a href="http://www.boost.org/doc/libs/release/libs/format/index.html">Boost.Format</a>:
try {
// ...
}
catch (senf::ExceptionMixin & e) {
e << boost::format("\n" "call id 0x%04x@%s") % id % address;
}
senf::SystemException is thrown for all operating system errors (failures which result in the
operating system setting the errno value). It is also derived from senf::Exception and can
therefore be extended as well.

Defining your own exception classes derived from senf::Exception is very simple:
struct FooException : public senf::Exception
{ FooException() : senf::Exception("Foo hit the fan") {} };
If SENF is compiled in debug mode (SENF_DEBUG is defined), the exception message will
automatically include a stack backtrace. For this to work, you need to add the
<tt>-rdynamic</tt> option to all link commands. This feature depends on <tt>gcc</tt> and
the GNU-libc.

To apply these features (extensibility, backtrace) to a non-senf exception, the non-senf
exception can be wrapped and re-thrown.
void foo() {
try {
// ... code that might throw std::bad_cast or somelib::FooException
}
SENF_WRAP_EXC(std::bad_cast)
SENF_WRAP_EXC(somelib::FooException)
}

The re-thrown exception can then be caught as std::bad_cast or as senf::ExceptionMixin as needed. It is safe, to wrap an exception twice (the macro will detect this case).

bar() {
try {
try {
foo();
}
catch (senf::ExceptionMixin & ex) {
ex << "\n" "add this info";
}
}
catch (std::bad_cast const & ex) {
std::cerr << ex.what() << std::endl;
}

The final error output will include

  • a backtrace if compiled in debug mode
  • the original error message from the std::bad_cast exception
  • the additional error message "add this info"
Todo:

Link against libcwd to add file-name/line-number information to the backtrace and remove the dependency on -rdynamic

Or better, use addr2line to obtain that information when showing the backtrace when catched within Daemon (addr2line -fsiCe argv[0])

Add signal handlers for the bad signals which writes a backtrace to stderr and terminates. This should probably write out a raw backtrace without de-mangling or line-numbers since we don't want to mess with dynamic memory when the heap might be corrupted ... Another handler for e.g. SIGUSR2 is nice to show a debug backtrace on demand

Macro Definition Documentation

◆ SENF_WRAP_EXC

#define SENF_WRAP_EXC (   Ex)
Value:
catch (Ex const & base) { \
if (dynamic_cast<senf::ExceptionMixin const *>(&base)) \
throw; \
else \
throw senf::WrapException<Ex>(base); \
}
Wrapper for standard non-senf exceptions.
Definition: Exception.hh:187

Wrap a non-senf exception.

This macro allows to wrap a non-senf exception adding functionality from ExceptionMixin using the WrapException template. For an example, see Exception classes.

Definition at line 217 of file Exception.hh.