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