Exception classes


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 Boost.Format:

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 -rdynamic option to all link commands. This feature depends on gcc 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


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

Defines

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

Define Documentation

#define
SENF_WRAP_EXC ( Ex  )

Value:

catch (Ex const & base) {                                                                 \
            if (dynamic_cast<senf::ExceptionMixin const *>(&base))                                \
                throw;                                                                            \
            else                                                                                  \
                throw senf::WrapException<Ex>(base);                                              \
        }
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 220 of file Exception.hh.