Include bind in ndnboost.
diff --git a/ndnboost/test/impl/execution_monitor.ipp b/ndnboost/test/impl/execution_monitor.ipp
new file mode 100644
index 0000000..5337347
--- /dev/null
+++ b/ndnboost/test/impl/execution_monitor.ipp
@@ -0,0 +1,1367 @@
+// (C) Copyright Gennadiy Rozental 2001-2008.
+// (C) Copyright Beman Dawes and Ullrich Koethe 1995-2001.
+// Use, modification, and distribution are subject to the
+// Boost Software License, Version 1.0. (See accompanying file
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/test for the library home page.
+//
+// File : $RCSfile$
+//
+// Version : $Revision: 57992 $
+//
+// Description : provides execution monitor implementation for all supported
+// configurations, including Microsoft structured exception based, unix signals
+// based and special workarounds for borland
+//
+// Note that when testing requirements or user wishes preclude use of this
+// file as a separate compilation unit, it may be included as a header file.
+//
+// Header dependencies are deliberately restricted to reduce coupling to other
+// boost libraries.
+// ***************************************************************************
+
+#ifndef BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER
+#define BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER
+
+// Boost.Test
+#include <ndnboost/test/detail/config.hpp>
+#include <ndnboost/test/detail/workaround.hpp>
+#include <ndnboost/test/execution_monitor.hpp>
+#include <ndnboost/test/debug.hpp>
+
+// Boost
+#include <ndnboost/cstdlib.hpp> // for exit codes
+#include <ndnboost/config.hpp> // for workarounds
+#include <ndnboost/exception/get_error_info.hpp> // for get_error_info
+#include <ndnboost/exception/current_exception_cast.hpp> // for current_exception_cast
+
+// STL
+#include <string> // for std::string
+#include <new> // for std::bad_alloc
+#include <typeinfo> // for std::bad_cast, std::bad_typeid
+#include <exception> // for std::exception, std::bad_exception
+#include <stdexcept> // for std exception hierarchy
+#include <cstring> // for C string API
+#include <cassert> // for assert
+#include <cstddef> // for NULL
+#include <cstdio> // for vsnprintf
+#include <cstdarg> // for varargs
+
+#ifdef BOOST_NO_STDC_NAMESPACE
+namespace std { using ::strerror; using ::strlen; using ::strncat; }
+#endif
+
+// to use vsnprintf
+#if defined(__SUNPRO_CC) || defined(__SunOS)
+# include <stdio.h>
+# include <stdarg.h>
+using std::va_list;
+#endif
+
+// to use vsnprintf
+#if defined(__QNXNTO__)
+# include <stdio.h>
+#endif
+
+#if defined(_WIN32) && !defined(BOOST_DISABLE_WIN32) && \
+ (!defined(__COMO__) && !defined(__MWERKS__) && !defined(__GNUC__) || \
+ BOOST_WORKAROUND(__MWERKS__, >= 0x3000))
+
+# define BOOST_SEH_BASED_SIGNAL_HANDLING
+
+# include <windows.h>
+
+# if defined(__MWERKS__) || (defined(_MSC_VER) && !defined(UNDER_CE))
+# include <eh.h>
+# endif
+
+# if defined(__BORLANDC__) && __BORLANDC__ >= 0x560 || defined(__MWERKS__)
+# include <stdint.h>
+# endif
+
+# if defined(__BORLANDC__) && __BORLANDC__ < 0x560
+ typedef unsigned uintptr_t;
+# endif
+
+# if BOOST_WORKAROUND(_MSC_VER, < 1300 ) || defined(UNDER_CE)
+typedef void* uintptr_t;
+# endif
+
+// for the FP control routines
+#include <float.h>
+
+#ifndef EM_INVALID
+#define EM_INVALID _EM_INVALID
+#endif
+
+#ifndef EM_DENORMAL
+#define EM_DENORMAL _EM_DENORMAL
+#endif
+
+#ifndef EM_ZERODIVIDE
+#define EM_ZERODIVIDE _EM_ZERODIVIDE
+#endif
+
+#ifndef EM_OVERFLOW
+#define EM_OVERFLOW _EM_OVERFLOW
+#endif
+
+#ifndef EM_UNDERFLOW
+#define EM_UNDERFLOW _EM_UNDERFLOW
+#endif
+
+#ifndef MCW_EM
+#define MCW_EM _MCW_EM
+#endif
+
+# if !defined(NDEBUG) && defined(_MSC_VER) && !defined(UNDER_CE)
+# include <crtdbg.h>
+# define BOOST_TEST_CRT_HOOK_TYPE _CRT_REPORT_HOOK
+# define BOOST_TEST_CRT_ASSERT _CRT_ASSERT
+# define BOOST_TEST_CRT_ERROR _CRT_ERROR
+# define BOOST_TEST_CRT_SET_HOOK(H) _CrtSetReportHook(H)
+# else
+# define BOOST_TEST_CRT_HOOK_TYPE void*
+# define BOOST_TEST_CRT_ASSERT 2
+# define BOOST_TEST_CRT_ERROR 1
+# define BOOST_TEST_CRT_SET_HOOK(H) (void*)(H)
+# endif
+
+# if !BOOST_WORKAROUND(_MSC_VER, >= 1400 ) || defined(UNDER_CE)
+
+typedef void* _invalid_parameter_handler;
+
+inline _invalid_parameter_handler
+_set_invalid_parameter_handler( _invalid_parameter_handler arg )
+{
+ return arg;
+}
+
+# endif
+
+# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564)) || defined(UNDER_CE)
+
+namespace { void _set_se_translator( void* ) {} }
+
+# endif
+
+#elif defined(BOOST_HAS_SIGACTION)
+
+# define BOOST_SIGACTION_BASED_SIGNAL_HANDLING
+
+# include <unistd.h>
+# include <signal.h>
+# include <setjmp.h>
+
+# if defined(__FreeBSD__)
+
+# ifndef SIGPOLL
+# define SIGPOLL SIGIO
+# endif
+
+# if (__FreeBSD_version < 70100)
+
+# define ILL_ILLADR 0 // ILL_RESAD_FAULT
+# define ILL_PRVOPC ILL_PRIVIN_FAULT
+# define ILL_ILLOPN 2 // ILL_RESOP_FAULT
+# define ILL_COPROC ILL_FPOP_FAULT
+
+# define BOOST_TEST_LIMITED_SIGNAL_DETAILS
+# define BOOST_TEST_IGNORE_SIGCHLD
+
+# endif
+# endif
+
+# if !defined(__CYGWIN__) && !defined(__QNXNTO__)
+# define BOOST_TEST_USE_ALT_STACK
+# endif
+
+# if defined(SIGPOLL) && !defined(__CYGWIN__) && \
+ !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) && \
+ !defined(__NetBSD__) && \
+ !defined(__QNXNTO__)
+# define BOOST_TEST_CATCH_SIGPOLL
+# endif
+
+# ifdef BOOST_TEST_USE_ALT_STACK
+# define BOOST_TEST_ALT_STACK_SIZE SIGSTKSZ
+# endif
+
+#else
+
+# define BOOST_NO_SIGNAL_HANDLING
+
+#endif
+
+#ifndef UNDER_CE
+#include <errno.h>
+#endif
+
+#include <ndnboost/test/detail/suppress_warnings.hpp>
+
+//____________________________________________________________________________//
+
+namespace ndnboost {
+
+// ************************************************************************** //
+// ************** report_error ************** //
+// ************************************************************************** //
+
+namespace detail {
+
+#ifdef __BORLANDC__
+# define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) std::vsnprintf( (a1), (a2), (a3), (a4) )
+#elif BOOST_WORKAROUND(_MSC_VER, <= 1310) || \
+ BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3000)) || \
+ defined(UNDER_CE)
+# define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) _vsnprintf( (a1), (a2), (a3), (a4) )
+#else
+# define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) vsnprintf( (a1), (a2), (a3), (a4) )
+#endif
+
+template <typename ErrorInfo>
+typename ErrorInfo::value_type
+extract( ndnboost::exception const* ex )
+{
+ if( !ex )
+ return 0;
+
+ typename ErrorInfo::value_type const * val = ndnboost::get_error_info<ErrorInfo>( *ex );
+
+ return val ? *val : 0;
+}
+
+//____________________________________________________________________________//
+
+static void
+report_error( execution_exception::error_code ec, ndnboost::exception const* be, char const* format, va_list* args )
+{
+ static const int REPORT_ERROR_BUFFER_SIZE = 512;
+ static char buf[REPORT_ERROR_BUFFER_SIZE];
+
+ BOOST_TEST_VSNPRINTF( buf, sizeof(buf)-1, format, *args );
+ buf[sizeof(buf)-1] = 0;
+
+ va_end( *args );
+
+ throw execution_exception( ec, buf, execution_exception::location( extract<throw_file>( be ),
+ extract<throw_line>( be ),
+ extract<throw_function>( be ) ) );
+}
+
+//____________________________________________________________________________//
+
+static void
+report_error( execution_exception::error_code ec, char const* format, ... )
+{
+ va_list args;
+ va_start( args, format );
+
+ report_error( ec, 0, format, &args );
+}
+
+//____________________________________________________________________________//
+
+static void
+report_error( execution_exception::error_code ec, ndnboost::exception const* be, char const* format, ... )
+{
+ va_list args;
+ va_start( args, format );
+
+ report_error( ec, be, format, &args );
+}
+
+//____________________________________________________________________________//
+
+template<typename Tr,typename Functor>
+inline int
+do_invoke( Tr const& tr, Functor const& F )
+{
+ return tr ? (*tr)( F ) : F();
+}
+
+//____________________________________________________________________________//
+
+} // namespace detail
+
+#if defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING)
+
+// ************************************************************************** //
+// ************** Sigaction based signal handling ************** //
+// ************************************************************************** //
+
+namespace detail {
+
+// ************************************************************************** //
+// ************** ndnboost::detail::system_signal_exception ************** //
+// ************************************************************************** //
+
+class system_signal_exception {
+public:
+ // Constructor
+ system_signal_exception()
+ : m_sig_info( 0 )
+ , m_context( 0 )
+ {}
+
+ // Access methods
+ void operator()( siginfo_t* i, void* c )
+ {
+ m_sig_info = i;
+ m_context = c;
+ }
+ void report() const;
+
+private:
+ // Data members
+ siginfo_t* m_sig_info; // system signal detailed info
+ void* m_context; // signal context
+};
+
+//____________________________________________________________________________//
+
+void
+system_signal_exception::report() const
+{
+ if( !m_sig_info )
+ return; // no error actually occur?
+
+ switch( m_sig_info->si_code ) {
+ case SI_USER:
+ report_error( execution_exception::system_error,
+ "signal: generated by kill() (or family); uid=%d; pid=%d",
+ (int)m_sig_info->si_uid, (int)m_sig_info->si_pid );
+ break;
+ case SI_QUEUE:
+ report_error( execution_exception::system_error,
+ "signal: sent by sigqueue()" );
+ break;
+ case SI_TIMER:
+ report_error( execution_exception::system_error,
+ "signal: the expiration of a timer set by timer_settimer()" );
+ break;
+ case SI_ASYNCIO:
+ report_error( execution_exception::system_error,
+ "signal: generated by the completion of an asynchronous I/O request" );
+ break;
+ case SI_MESGQ:
+ report_error( execution_exception::system_error,
+ "signal: generated by the the arrival of a message on an empty message queue" );
+ break;
+ default:
+ break;
+ }
+
+ switch( m_sig_info->si_signo ) {
+ case SIGILL:
+ switch( m_sig_info->si_code ) {
+#ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
+ case ILL_ILLOPC:
+ report_error( execution_exception::system_fatal_error,
+ "signal: illegal opcode; address of failing instruction: 0x%08lx",
+ m_sig_info->si_addr );
+ break;
+ case ILL_ILLTRP:
+ report_error( execution_exception::system_fatal_error,
+ "signal: illegal trap; address of failing instruction: 0x%08lx",
+ m_sig_info->si_addr );
+ break;
+ case ILL_PRVREG:
+ report_error( execution_exception::system_fatal_error,
+ "signal: privileged register; address of failing instruction: 0x%08lx",
+ m_sig_info->si_addr );
+ break;
+ case ILL_BADSTK:
+ report_error( execution_exception::system_fatal_error,
+ "signal: internal stack error; address of failing instruction: 0x%08lx",
+ m_sig_info->si_addr );
+ break;
+#endif
+ case ILL_ILLOPN:
+ report_error( execution_exception::system_fatal_error,
+ "signal: illegal operand; address of failing instruction: 0x%08lx",
+ m_sig_info->si_addr );
+ break;
+ case ILL_ILLADR:
+ report_error( execution_exception::system_fatal_error,
+ "signal: illegal addressing mode; address of failing instruction: 0x%08lx",
+ m_sig_info->si_addr );
+ break;
+ case ILL_PRVOPC:
+ report_error( execution_exception::system_fatal_error,
+ "signal: privileged opcode; address of failing instruction: 0x%08lx",
+ m_sig_info->si_addr );
+ break;
+ case ILL_COPROC:
+ report_error( execution_exception::system_fatal_error,
+ "signal: co-processor error; address of failing instruction: 0x%08lx",
+ m_sig_info->si_addr );
+ break;
+ default:
+ report_error( execution_exception::system_fatal_error,
+ "signal: SIGILL, si_code: %d (illegal instruction; address of failing instruction: 0x%08lx)",
+ m_sig_info->si_addr, m_sig_info->si_code );
+ break;
+ }
+ break;
+
+ case SIGFPE:
+ switch( m_sig_info->si_code ) {
+ case FPE_INTDIV:
+ report_error( execution_exception::system_error,
+ "signal: integer divide by zero; address of failing instruction: 0x%08lx",
+ m_sig_info->si_addr );
+ break;
+ case FPE_INTOVF:
+ report_error( execution_exception::system_error,
+ "signal: integer overflow; address of failing instruction: 0x%08lx",
+ m_sig_info->si_addr );
+ break;
+ case FPE_FLTDIV:
+ report_error( execution_exception::system_error,
+ "signal: floating point divide by zero; address of failing instruction: 0x%08lx",
+ m_sig_info->si_addr );
+ break;
+ case FPE_FLTOVF:
+ report_error( execution_exception::system_error,
+ "signal: floating point overflow; address of failing instruction: 0x%08lx",
+ m_sig_info->si_addr );
+ break;
+ case FPE_FLTUND:
+ report_error( execution_exception::system_error,
+ "signal: floating point underflow; address of failing instruction: 0x%08lx",
+ m_sig_info->si_addr );
+ break;
+ case FPE_FLTRES:
+ report_error( execution_exception::system_error,
+ "signal: floating point inexact result; address of failing instruction: 0x%08lx",
+ m_sig_info->si_addr );
+ break;
+ case FPE_FLTINV:
+ report_error( execution_exception::system_error,
+ "signal: invalid floating point operation; address of failing instruction: 0x%08lx",
+ m_sig_info->si_addr );
+ break;
+ case FPE_FLTSUB:
+ report_error( execution_exception::system_error,
+ "signal: subscript out of range; address of failing instruction: 0x%08lx",
+ m_sig_info->si_addr );
+ break;
+ default:
+ report_error( execution_exception::system_error,
+ "signal: SIGFPE, si_code: %d (errnoneous arithmetic operations; address of failing instruction: 0x%08lx)",
+ m_sig_info->si_addr, m_sig_info->si_code );
+ break;
+ }
+ break;
+
+ case SIGSEGV:
+ switch( m_sig_info->si_code ) {
+#ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
+ case SEGV_MAPERR:
+ report_error( execution_exception::system_fatal_error,
+ "memory access violation at address: 0x%08lx: no mapping at fault address",
+ m_sig_info->si_addr );
+ break;
+ case SEGV_ACCERR:
+ report_error( execution_exception::system_fatal_error,
+ "memory access violation at address: 0x%08lx: invalid permissions",
+ m_sig_info->si_addr );
+ break;
+#endif
+ default:
+ report_error( execution_exception::system_fatal_error,
+ "signal: SIGSEGV, si_code: %d (memory access violation at address: 0x%08lx)",
+ m_sig_info->si_addr, m_sig_info->si_code );
+ break;
+ }
+ break;
+
+ case SIGBUS:
+ switch( m_sig_info->si_code ) {
+#ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
+ case BUS_ADRALN:
+ report_error( execution_exception::system_fatal_error,
+ "memory access violation at address: 0x%08lx: invalid address alignment",
+ m_sig_info->si_addr );
+ break;
+ case BUS_ADRERR:
+ report_error( execution_exception::system_fatal_error,
+ "memory access violation at address: 0x%08lx: non-existent physical address",
+ m_sig_info->si_addr );
+ break;
+ case BUS_OBJERR:
+ report_error( execution_exception::system_fatal_error,
+ "memory access violation at address: 0x%08lx: object specific hardware error",
+ m_sig_info->si_addr );
+ break;
+#endif
+ default:
+ report_error( execution_exception::system_fatal_error,
+ "signal: SIGSEGV, si_code: %d (memory access violation at address: 0x%08lx)",
+ m_sig_info->si_addr, m_sig_info->si_code );
+ break;
+ }
+ break;
+
+ case SIGCHLD:
+ switch( m_sig_info->si_code ) {
+#ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
+ case CLD_EXITED:
+ report_error( execution_exception::system_error,
+ "child has exited; pid: %d; uid: %d; exit value: %d",
+ (int)m_sig_info->si_pid, (int)m_sig_info->si_uid, (int)m_sig_info->si_status );
+ break;
+ case CLD_KILLED:
+ report_error( execution_exception::system_error,
+ "child was killed; pid: %d; uid: %d; exit value: %d",
+ (int)m_sig_info->si_pid, (int)m_sig_info->si_uid, (int)m_sig_info->si_status );
+ break;
+ case CLD_DUMPED:
+ report_error( execution_exception::system_error,
+ "child terminated abnormally; pid: %d; uid: %d; exit value: %d",
+ (int)m_sig_info->si_pid, (int)m_sig_info->si_uid, (int)m_sig_info->si_status );
+ break;
+ case CLD_TRAPPED:
+ report_error( execution_exception::system_error,
+ "traced child has trapped; pid: %d; uid: %d; exit value: %d",
+ (int)m_sig_info->si_pid, (int)m_sig_info->si_uid, (int)m_sig_info->si_status );
+ break;
+ case CLD_STOPPED:
+ report_error( execution_exception::system_error,
+ "child has stopped; pid: %d; uid: %d; exit value: %d",
+ (int)m_sig_info->si_pid, (int)m_sig_info->si_uid, (int)m_sig_info->si_status );
+ break;
+ case CLD_CONTINUED:
+ report_error( execution_exception::system_error,
+ "stopped child had continued; pid: %d; uid: %d; exit value: %d",
+ (int)m_sig_info->si_pid, (int)m_sig_info->si_uid, (int)m_sig_info->si_status );
+ break;
+#endif
+ default:
+ report_error( execution_exception::system_error,
+ "signal: SIGCHLD, si_code: %d (child process has terminated; pid: %d; uid: %d; exit value: %d)",
+ (int)m_sig_info->si_pid, (int)m_sig_info->si_uid, (int)m_sig_info->si_status, m_sig_info->si_code );
+ break;
+ }
+ break;
+
+#if defined(BOOST_TEST_CATCH_SIGPOLL)
+
+ case SIGPOLL:
+ switch( m_sig_info->si_code ) {
+#ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
+ case POLL_IN:
+ report_error( execution_exception::system_error,
+ "data input available; band event %d",
+ (int)m_sig_info->si_band );
+ break;
+ case POLL_OUT:
+ report_error( execution_exception::system_error,
+ "output buffers available; band event %d",
+ (int)m_sig_info->si_band );
+ break;
+ case POLL_MSG:
+ report_error( execution_exception::system_error,
+ "input message available; band event %d",
+ (int)m_sig_info->si_band );
+ break;
+ case POLL_ERR:
+ report_error( execution_exception::system_error,
+ "i/o error; band event %d",
+ (int)m_sig_info->si_band );
+ break;
+ case POLL_PRI:
+ report_error( execution_exception::system_error,
+ "high priority input available; band event %d",
+ (int)m_sig_info->si_band );
+ break;
+#if defined(POLL_ERR) && defined(POLL_HUP) && (POLL_ERR - POLL_HUP)
+ case POLL_HUP:
+ report_error( execution_exception::system_error,
+ "device disconnected; band event %d",
+ (int)m_sig_info->si_band );
+ break;
+#endif
+#endif
+ default:
+ report_error( execution_exception::system_error,
+ "signal: SIGPOLL, si_code: %d (asynchronous I/O event occured; band event %d)",
+ (int)m_sig_info->si_band, m_sig_info->si_code );
+ break;
+ }
+ break;
+
+#endif
+
+ case SIGABRT:
+ report_error( execution_exception::system_error,
+ "signal: SIGABRT (application abort requested)" );
+ break;
+
+ case SIGALRM:
+ report_error( execution_exception::timeout_error,
+ "signal: SIGALRM (timeout while executing function)" );
+ break;
+
+ default:
+ report_error( execution_exception::system_error, "unrecognized signal" );
+ }
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** ndnboost::detail::signal_action ************** //
+// ************************************************************************** //
+
+// Forward declaration
+extern "C" {
+static void execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context );
+static void execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context );
+}
+
+class signal_action {
+ typedef struct sigaction* sigaction_ptr;
+public:
+ //Constructor
+ signal_action();
+ signal_action( int sig, bool install, bool attach_dbg, char* alt_stack );
+ ~signal_action();
+
+private:
+ // Data members
+ int m_sig;
+ bool m_installed;
+ struct sigaction m_new_action;
+ struct sigaction m_old_action;
+};
+
+//____________________________________________________________________________//
+
+signal_action::signal_action()
+: m_installed( false )
+{}
+
+//____________________________________________________________________________//
+
+signal_action::signal_action( int sig, bool install, bool attach_dbg, char* alt_stack )
+: m_sig( sig )
+, m_installed( install )
+{
+ if( !install )
+ return;
+
+ std::memset( &m_new_action, 0, sizeof(struct sigaction) );
+
+ BOOST_TEST_SYS_ASSERT( ::sigaction( m_sig , sigaction_ptr(), &m_new_action ) != -1 );
+
+ if( m_new_action.sa_sigaction || m_new_action.sa_handler ) {
+ m_installed = false;
+ return;
+ }
+
+ m_new_action.sa_flags |= SA_SIGINFO;
+ m_new_action.sa_sigaction = attach_dbg ? &execution_monitor_attaching_signal_handler
+ : &execution_monitor_jumping_signal_handler;
+ BOOST_TEST_SYS_ASSERT( sigemptyset( &m_new_action.sa_mask ) != -1 );
+
+#ifdef BOOST_TEST_USE_ALT_STACK
+ if( alt_stack )
+ m_new_action.sa_flags |= SA_ONSTACK;
+#endif
+
+ BOOST_TEST_SYS_ASSERT( ::sigaction( m_sig, &m_new_action, &m_old_action ) != -1 );
+}
+
+//____________________________________________________________________________//
+
+signal_action::~signal_action()
+{
+ if( m_installed )
+ ::sigaction( m_sig, &m_old_action , sigaction_ptr() );
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** ndnboost::detail::signal_handler ************** //
+// ************************************************************************** //
+
+class signal_handler {
+public:
+ // Constructor
+ explicit signal_handler( bool catch_system_errors, int timeout, bool attach_dbg, char* alt_stack );
+
+ // Destructor
+ ~signal_handler();
+
+ // access methods
+ static sigjmp_buf& jump_buffer()
+ {
+ assert( !!s_active_handler );
+
+ return s_active_handler->m_sigjmp_buf;
+ }
+
+ static system_signal_exception& sys_sig()
+ {
+ assert( !!s_active_handler );
+
+ return s_active_handler->m_sys_sig;
+ }
+
+private:
+ // Data members
+ signal_handler* m_prev_handler;
+ int m_timeout;
+
+ signal_action m_ILL_action;
+ signal_action m_FPE_action;
+ signal_action m_SEGV_action;
+ signal_action m_BUS_action;
+ signal_action m_CHLD_action;
+ signal_action m_POLL_action;
+ signal_action m_ABRT_action;
+ signal_action m_ALRM_action;
+
+ sigjmp_buf m_sigjmp_buf;
+ system_signal_exception m_sys_sig;
+
+ static signal_handler* s_active_handler;
+};
+
+// !! need to be placed in thread specific storage
+typedef signal_handler* signal_handler_ptr;
+signal_handler* signal_handler::s_active_handler = signal_handler_ptr();
+
+//____________________________________________________________________________//
+
+signal_handler::signal_handler( bool catch_system_errors, int timeout, bool attach_dbg, char* alt_stack )
+: m_prev_handler( s_active_handler )
+, m_timeout( timeout )
+, m_ILL_action ( SIGILL , catch_system_errors, attach_dbg, alt_stack )
+, m_FPE_action ( SIGFPE , catch_system_errors, attach_dbg, alt_stack )
+, m_SEGV_action( SIGSEGV, catch_system_errors, attach_dbg, alt_stack )
+, m_BUS_action ( SIGBUS , catch_system_errors, attach_dbg, alt_stack )
+#ifndef BOOST_TEST_IGNORE_SIGCHLD
+, m_CHLD_action( SIGCHLD, catch_system_errors, attach_dbg, alt_stack )
+#endif
+#ifdef BOOST_TEST_CATCH_SIGPOLL
+, m_POLL_action( SIGPOLL, catch_system_errors, attach_dbg, alt_stack )
+#endif
+, m_ABRT_action( SIGABRT, catch_system_errors, attach_dbg, alt_stack )
+, m_ALRM_action( SIGALRM, timeout > 0 , attach_dbg, alt_stack )
+{
+ s_active_handler = this;
+
+ if( m_timeout > 0 ) {
+ ::alarm( 0 );
+ ::alarm( timeout );
+ }
+
+#ifdef BOOST_TEST_USE_ALT_STACK
+ if( alt_stack ) {
+ stack_t sigstk;
+ std::memset( &sigstk, 0, sizeof(stack_t) );
+
+ BOOST_TEST_SYS_ASSERT( ::sigaltstack( 0, &sigstk ) != -1 );
+
+ if( sigstk.ss_flags & SS_DISABLE ) {
+ sigstk.ss_sp = alt_stack;
+ sigstk.ss_size = BOOST_TEST_ALT_STACK_SIZE;
+ sigstk.ss_flags = 0;
+ BOOST_TEST_SYS_ASSERT( ::sigaltstack( &sigstk, 0 ) != -1 );
+ }
+ }
+#endif
+}
+
+//____________________________________________________________________________//
+
+signal_handler::~signal_handler()
+{
+ assert( s_active_handler == this );
+
+ if( m_timeout > 0 )
+ ::alarm( 0 );
+
+#ifdef BOOST_TEST_USE_ALT_STACK
+#ifdef __GNUC__
+ // We shouldn't need to explicitly initialize all the members here,
+ // but gcc warns if we don't, so add initializers for each of the
+ // members specified in the POSIX std:
+ stack_t sigstk = { 0, 0, 0 };
+#else
+ stack_t sigstk = { };
+#endif
+
+ sigstk.ss_size = MINSIGSTKSZ;
+ sigstk.ss_flags = SS_DISABLE;
+ BOOST_TEST_SYS_ASSERT( ::sigaltstack( &sigstk, 0 ) != -1 );
+#endif
+
+ s_active_handler = m_prev_handler;
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** execution_monitor_signal_handler ************** //
+// ************************************************************************** //
+
+extern "C" {
+
+static bool ignore_sigchild( siginfo_t* info )
+{
+ return info->si_signo == SIGCHLD
+#ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
+ && info->si_code == CLD_EXITED
+#endif
+#ifdef BOOST_TEST_IGNORE_NON_ZERO_CHILD_CODE
+ ;
+#else
+ && (int)info->si_status == 0;
+#endif
+}
+
+//____________________________________________________________________________//
+
+static void execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context )
+{
+ if( ignore_sigchild( info ) )
+ return;
+
+ signal_handler::sys_sig()( info, context );
+
+ siglongjmp( signal_handler::jump_buffer(), sig );
+}
+
+//____________________________________________________________________________//
+
+static void execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context )
+{
+ if( ignore_sigchild( info ) )
+ return;
+
+ if( !debug::attach_debugger( false ) )
+ execution_monitor_jumping_signal_handler( sig, info, context );
+
+ // debugger attached; it will handle the signal
+ BOOST_TEST_SYS_ASSERT( ::signal( sig, SIG_DFL ) != SIG_ERR );
+}
+
+//____________________________________________________________________________//
+
+}
+
+} // namespace detail
+
+// ************************************************************************** //
+// ************** execution_monitor::catch_signals ************** //
+// ************************************************************************** //
+
+int
+execution_monitor::catch_signals( unit_test::callback0<int> const& F )
+{
+ using namespace detail;
+
+#if defined(__CYGWIN__)
+ p_catch_system_errors.value = false;
+#endif
+
+#ifdef BOOST_TEST_USE_ALT_STACK
+ if( !!p_use_alt_stack && !m_alt_stack )
+ m_alt_stack.reset( new char[BOOST_TEST_ALT_STACK_SIZE] );
+#else
+ p_use_alt_stack.value = false;
+#endif
+
+ signal_handler local_signal_handler( p_catch_system_errors, p_timeout, p_auto_start_dbg,
+ !p_use_alt_stack ? 0 : m_alt_stack.get() );
+
+ if( !sigsetjmp( signal_handler::jump_buffer(), 1 ) )
+ return detail::do_invoke( m_custom_translators , F );
+ else
+ throw local_signal_handler.sys_sig();
+}
+
+//____________________________________________________________________________//
+
+#elif defined(BOOST_SEH_BASED_SIGNAL_HANDLING)
+
+// ************************************************************************** //
+// ************** Microsoft structured exception handling ************** //
+// ************************************************************************** //
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
+namespace { void _set_se_translator( void* ) {} }
+#endif
+
+namespace detail {
+
+// ************************************************************************** //
+// ************** ndnboost::detail::system_signal_exception ************** //
+// ************************************************************************** //
+
+class system_signal_exception {
+public:
+ // Constructor
+ explicit system_signal_exception( execution_monitor* em )
+ : m_em( em )
+ , m_se_id( 0 )
+ , m_fault_address( 0 )
+ , m_dir( false )
+ {}
+
+ void report() const;
+ int operator()( unsigned int id, _EXCEPTION_POINTERS* exps );
+
+private:
+ // Data members
+ execution_monitor* m_em;
+
+ unsigned int m_se_id;
+ void* m_fault_address;
+ bool m_dir;
+};
+
+static void
+seh_catch_preventer( unsigned int /* id */, _EXCEPTION_POINTERS* /* exps */ )
+{
+ throw;
+}
+
+//____________________________________________________________________________//
+
+int
+system_signal_exception::operator()( unsigned int id, _EXCEPTION_POINTERS* exps )
+{
+ const unsigned int MSFT_CPP_EXCEPT = 0xE06d7363; // EMSC
+
+ if( !m_em->p_catch_system_errors || (id == MSFT_CPP_EXCEPT) )
+ return EXCEPTION_CONTINUE_SEARCH;
+
+ if( !!m_em->p_auto_start_dbg && debug::attach_debugger( false ) ) {
+ m_em->p_catch_system_errors.value = false;
+ _set_se_translator( &seh_catch_preventer );
+
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+
+ m_se_id = id;
+ if( m_se_id == EXCEPTION_ACCESS_VIOLATION && exps->ExceptionRecord->NumberParameters == 2 ) {
+ m_fault_address = (void*)exps->ExceptionRecord->ExceptionInformation[1];
+ m_dir = exps->ExceptionRecord->ExceptionInformation[0] == 0;
+ }
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+//____________________________________________________________________________//
+
+void
+system_signal_exception::report() const
+{
+ switch( m_se_id ) {
+ // cases classified as system_fatal_error
+ case EXCEPTION_ACCESS_VIOLATION: {
+ if( !m_fault_address )
+ detail::report_error( execution_exception::system_fatal_error, "memory access violation" );
+ else
+ detail::report_error(
+ execution_exception::system_fatal_error,
+ "memory access violation occurred at address 0x%08lx, while attempting to %s",
+ m_fault_address,
+ m_dir ? " read inaccessible data"
+ : " write to an inaccessible (or protected) address"
+ );
+ break;
+ }
+
+ case EXCEPTION_ILLEGAL_INSTRUCTION:
+ detail::report_error( execution_exception::system_fatal_error, "illegal instruction" );
+ break;
+
+ case EXCEPTION_PRIV_INSTRUCTION:
+ detail::report_error( execution_exception::system_fatal_error, "tried to execute an instruction whose operation is not allowed in the current machine mode" );
+ break;
+
+ case EXCEPTION_IN_PAGE_ERROR:
+ detail::report_error( execution_exception::system_fatal_error, "access to a memory page that is not present" );
+ break;
+
+ case EXCEPTION_STACK_OVERFLOW:
+ detail::report_error( execution_exception::system_fatal_error, "stack overflow" );
+ break;
+
+ case EXCEPTION_NONCONTINUABLE_EXCEPTION:
+ detail::report_error( execution_exception::system_fatal_error, "tried to continue execution after a non continuable exception occurred" );
+ break;
+
+ // cases classified as (non-fatal) system_trap
+ case EXCEPTION_DATATYPE_MISALIGNMENT:
+ detail::report_error( execution_exception::system_error, "data misalignment" );
+ break;
+
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ detail::report_error( execution_exception::system_error, "integer divide by zero" );
+ break;
+
+ case EXCEPTION_INT_OVERFLOW:
+ detail::report_error( execution_exception::system_error, "integer overflow" );
+ break;
+
+ case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+ detail::report_error( execution_exception::system_error, "array bounds exceeded" );
+ break;
+
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+ detail::report_error( execution_exception::system_error, "floating point divide by zero" );
+ break;
+
+ case EXCEPTION_FLT_STACK_CHECK:
+ detail::report_error( execution_exception::system_error,
+ "stack overflowed or underflowed as the result of a floating-point operation" );
+ break;
+
+ case EXCEPTION_FLT_DENORMAL_OPERAND:
+ detail::report_error( execution_exception::system_error,
+ "operand of floating point operation is denormal" );
+ break;
+
+# if 0 // !! ??
+ case EXCEPTION_FLT_INEXACT_RESULT:
+ detail::report_error( execution_exception::system_error,
+ "result of a floating-point operation cannot be represented exactly" );
+ break;
+#endif
+
+ case EXCEPTION_FLT_OVERFLOW:
+ detail::report_error( execution_exception::system_error,
+ "exponent of a floating-point operation is greater than the magnitude allowed by the corresponding type" );
+ break;
+
+ case EXCEPTION_FLT_UNDERFLOW:
+ detail::report_error( execution_exception::system_error,
+ "exponent of a floating-point operation is less than the magnitude allowed by the corresponding type" );
+ break;
+
+ case EXCEPTION_FLT_INVALID_OPERATION:
+ detail::report_error( execution_exception::system_error, "floating point error" );
+ break;
+
+ case EXCEPTION_BREAKPOINT:
+ detail::report_error( execution_exception::system_error, "breakpoint encountered" );
+ break;
+
+ default:
+ detail::report_error( execution_exception::system_error, "unrecognized exception. Id: 0x%08lx", m_se_id );
+ break;
+ }
+}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** assert_reporting_function ************** //
+// ************************************************************************** //
+
+int BOOST_TEST_CALL_DECL
+assert_reporting_function( int reportType, char* userMessage, int* )
+{
+ switch( reportType ) {
+ case BOOST_TEST_CRT_ASSERT:
+ detail::report_error( execution_exception::user_error, userMessage );
+
+ return 1; // return value and retVal are not important since we never reach this line
+ case BOOST_TEST_CRT_ERROR:
+ detail::report_error( execution_exception::system_error, userMessage );
+
+ return 1; // return value and retVal are not important since we never reach this line
+ default:
+ return 0; // use usual reporting method
+ }
+} // assert_reporting_function
+
+//____________________________________________________________________________//
+
+void BOOST_TEST_CALL_DECL
+invalid_param_handler( wchar_t const* /* expr */,
+ wchar_t const* /* func */,
+ wchar_t const* /* file */,
+ unsigned int /* line */,
+ uintptr_t /* reserved */)
+{
+ detail::report_error( execution_exception::user_error,
+ "Invalid parameter detected by C runtime library" );
+}
+
+//____________________________________________________________________________//
+
+void BOOST_TEST_CALL_DECL
+switch_fp_exceptions( bool on_off )
+{
+ if( !on_off )
+ _clearfp();
+
+ int cw = ::_controlfp( 0, 0 );
+
+ int exceptions_mask = EM_INVALID|EM_DENORMAL|EM_ZERODIVIDE|EM_OVERFLOW|EM_UNDERFLOW;
+
+ if( on_off )
+ cw &= ~exceptions_mask; // Set the exception masks on, turn exceptions off
+ else
+ cw |= exceptions_mask; // Set the exception masks off, turn exceptions on
+
+ if( on_off )
+ _clearfp();
+
+ // Set the control word
+ ::_controlfp( cw, MCW_EM );
+}
+
+//____________________________________________________________________________//
+
+} // namespace detail
+
+// ************************************************************************** //
+// ************** execution_monitor::catch_signals ************** //
+// ************************************************************************** //
+
+int
+execution_monitor::catch_signals( unit_test::callback0<int> const& F )
+{
+ _invalid_parameter_handler old_iph = _invalid_parameter_handler();
+ BOOST_TEST_CRT_HOOK_TYPE old_crt_hook = 0;
+
+ if( !p_catch_system_errors )
+ _set_se_translator( &detail::seh_catch_preventer );
+ else {
+ if( !!p_detect_fp_exceptions )
+ detail::switch_fp_exceptions( true );
+
+ old_crt_hook = BOOST_TEST_CRT_SET_HOOK( &detail::assert_reporting_function );
+
+ old_iph = _set_invalid_parameter_handler(
+ reinterpret_cast<_invalid_parameter_handler>( &detail::invalid_param_handler ) );
+ }
+
+ detail::system_signal_exception SSE( this );
+
+ int ret_val = 0;
+
+ __try {
+ __try {
+ ret_val = detail::do_invoke( m_custom_translators, F );
+ }
+ __except( SSE( GetExceptionCode(), GetExceptionInformation() ) ) {
+ throw SSE;
+ }
+ }
+ __finally {
+ if( !!p_catch_system_errors ) {
+ if( !!p_detect_fp_exceptions )
+ detail::switch_fp_exceptions( false );
+
+ BOOST_TEST_CRT_SET_HOOK( old_crt_hook );
+
+ _set_invalid_parameter_handler( old_iph );
+ }
+ }
+
+ return ret_val;
+}
+
+//____________________________________________________________________________//
+
+#else // default signal handler
+
+namespace detail {
+
+class system_signal_exception {
+public:
+ void report() const {}
+};
+
+} // namespace detail
+
+int
+execution_monitor::catch_signals( unit_test::callback0<int> const& F )
+{
+ return detail::do_invoke( m_custom_translators , F );
+}
+
+//____________________________________________________________________________//
+
+#endif // choose signal handler
+
+// ************************************************************************** //
+// ************** execution_monitor::execute ************** //
+// ************************************************************************** //
+
+int
+execution_monitor::execute( unit_test::callback0<int> const& F )
+{
+ if( debug::under_debugger() )
+ p_catch_system_errors.value = false;
+
+ try {
+ return catch_signals( F );
+ }
+
+ // Catch-clause reference arguments are a bit different from function
+ // arguments (ISO 15.3 paragraphs 18 & 19). Apparently const isn't
+ // required. Programmers ask for const anyhow, so we supply it. That's
+ // easier than answering questions about non-const usage.
+
+ catch( char const* ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ "C string: %s", ex ); }
+ catch( std::string const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ "std::string: %s", ex.c_str() ); }
+
+ // std:: exceptions
+
+ catch( std::bad_alloc const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ current_exception_cast<ndnboost::exception const>(),
+ "std::bad_alloc: %s", ex.what() ); }
+
+#if BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
+ catch( std::bad_cast const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ current_exception_cast<ndnboost::exception const>(),
+ "std::bad_cast" ); }
+ catch( std::bad_typeid const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ current_exception_cast<ndnboost::exception const>(),
+ "std::bad_typeid" ); }
+#else
+ catch( std::bad_cast const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ current_exception_cast<ndnboost::exception const>(),
+ "std::bad_cast: %s", ex.what() ); }
+ catch( std::bad_typeid const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ current_exception_cast<ndnboost::exception const>(),
+ "std::bad_typeid: %s", ex.what() ); }
+#endif
+
+ catch( std::bad_exception const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ current_exception_cast<ndnboost::exception const>(),
+ "std::bad_exception: %s", ex.what() ); }
+ catch( std::domain_error const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ current_exception_cast<ndnboost::exception const>(),
+ "std::domain_error: %s", ex.what() ); }
+ catch( std::invalid_argument const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ current_exception_cast<ndnboost::exception const>(),
+ "std::invalid_argument: %s", ex.what() ); }
+ catch( std::length_error const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ current_exception_cast<ndnboost::exception const>(),
+ "std::length_error: %s", ex.what() ); }
+ catch( std::out_of_range const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ current_exception_cast<ndnboost::exception const>(),
+ "std::out_of_range: %s", ex.what() ); }
+ catch( std::range_error const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ current_exception_cast<ndnboost::exception const>(),
+ "std::range_error: %s", ex.what() ); }
+ catch( std::overflow_error const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ current_exception_cast<ndnboost::exception const>(),
+ "std::overflow_error: %s", ex.what() ); }
+ catch( std::underflow_error const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ current_exception_cast<ndnboost::exception const>(),
+ "std::underflow_error: %s", ex.what() ); }
+ catch( std::logic_error const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ current_exception_cast<ndnboost::exception const>(),
+ "std::logic_error: %s", ex.what() ); }
+ catch( std::runtime_error const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ current_exception_cast<ndnboost::exception const>(),
+ "std::runtime_error: %s", ex.what() ); }
+ catch( std::exception const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ current_exception_cast<ndnboost::exception const>(),
+ "std::exception: %s", ex.what() ); }
+
+ catch( ndnboost::exception const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ &ex,
+ "unknown ndnboost::exception" ); }
+
+ // system errors
+ catch( system_error const& ex )
+ { detail::report_error( execution_exception::cpp_exception_error,
+ "system_error produced by: %s: %s", ex.p_failed_exp.get(), std::strerror( ex.p_errno ) ); }
+ catch( detail::system_signal_exception const& ex )
+ { ex.report(); }
+
+ // not an error
+ catch( execution_aborted const& )
+ { return 0; }
+
+ // just forward
+ catch( execution_exception const& )
+ { throw; }
+
+ // unknown error
+ catch( ... )
+ { detail::report_error( execution_exception::cpp_exception_error, "unknown type" ); }
+
+ return 0; // never reached; supplied to quiet compiler warnings
+} // execute
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** system_error ************** //
+// ************************************************************************** //
+
+system_error::system_error( char const* exp )
+#ifdef UNDER_CE
+: p_errno( GetLastError() )
+#else
+: p_errno( errno )
+#endif
+, p_failed_exp( exp )
+{}
+
+//____________________________________________________________________________//
+
+// ************************************************************************** //
+// ************** execution_exception ************** //
+// ************************************************************************** //
+
+execution_exception::execution_exception( error_code ec_, const_string what_msg_, location const& location_ )
+: m_error_code( ec_ )
+, m_what( what_msg_.empty() ? BOOST_TEST_L( "uncaught exception, system error or abort requested" ) : what_msg_ )
+, m_location( location_ )
+{}
+
+//____________________________________________________________________________//
+
+execution_exception::location::location( char const* file_name, size_t line_num, char const* func )
+: m_file_name( file_name ? file_name : "unknown location" )
+, m_line_num( line_num )
+, m_function( func )
+{}
+
+//____________________________________________________________________________//
+
+} // namespace ndnboost
+
+#include <ndnboost/test/detail/enable_warnings.hpp>
+
+#endif // BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER
+