1440 lines
		
	
	
		
			50 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			1440 lines
		
	
	
		
			50 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
//  (C) Copyright Gennadiy Rozental 2001.
 | 
						|
//  (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
 | 
						|
///  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 <boost/test/detail/config.hpp>
 | 
						|
#include <boost/test/detail/workaround.hpp>
 | 
						|
#include <boost/test/detail/throw_exception.hpp>
 | 
						|
#include <boost/test/execution_monitor.hpp>
 | 
						|
#include <boost/test/debug.hpp>
 | 
						|
 | 
						|
// Boost
 | 
						|
#include <boost/cstdlib.hpp>    // for exit codes
 | 
						|
#include <boost/config.hpp>     // for workarounds
 | 
						|
#include <boost/core/ignore_unused.hpp> // for ignore_unused
 | 
						|
#ifndef BOOST_NO_EXCEPTION
 | 
						|
#include <boost/exception/get_error_info.hpp> // for get_error_info
 | 
						|
#include <boost/exception/current_exception_cast.hpp> // for current_exception_cast
 | 
						|
#endif
 | 
						|
 | 
						|
// 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
 | 
						|
 | 
						|
#include <iostream>              // 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>
 | 
						|
using std::va_list;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef 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 defined(UNDER_CE) && BOOST_WORKAROUND(_MSC_VER,  < 1500 )
 | 
						|
   typedef void* uintptr_t;
 | 
						|
#  elif defined(UNDER_CE)
 | 
						|
#  include <crtdefs.h>
 | 
						|
#  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(BOOST_COMO)) || 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__)
 | 
						|
 | 
						|
#    include <osreldate.h>
 | 
						|
 | 
						|
#    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
 | 
						|
 | 
						|
#    endif
 | 
						|
#  endif
 | 
						|
 | 
						|
#  if defined(__ANDROID__)
 | 
						|
#    include <android/api-level.h>
 | 
						|
#  endif
 | 
						|
 | 
						|
// documentation of BOOST_TEST_DISABLE_ALT_STACK in execution_monitor.hpp
 | 
						|
#  if !defined(__CYGWIN__) && !defined(__QNXNTO__) && !defined(__bgq__) && \
 | 
						|
   (!defined(__ANDROID__) || __ANDROID_API__ >= 8) && \
 | 
						|
   !defined(BOOST_TEST_DISABLE_ALT_STACK)
 | 
						|
#    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
 | 
						|
 | 
						|
#if !defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
 | 
						|
#  include <boost/core/demangle.hpp>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <boost/test/detail/suppress_warnings.hpp>
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
namespace boost {
 | 
						|
 | 
						|
// ************************************************************************** //
 | 
						|
// **************                 throw_exception              ************** //
 | 
						|
// ************************************************************************** //
 | 
						|
 | 
						|
#ifdef BOOST_NO_EXCEPTION
 | 
						|
void throw_exception( std::exception const & e ) { abort(); }
 | 
						|
#endif
 | 
						|
 | 
						|
// ************************************************************************** //
 | 
						|
// **************                  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
 | 
						|
 | 
						|
#ifndef BOOST_NO_EXCEPTION
 | 
						|
 | 
						|
template <typename ErrorInfo>
 | 
						|
typename ErrorInfo::value_type
 | 
						|
extract( boost::exception const* ex )
 | 
						|
{
 | 
						|
    if( !ex )
 | 
						|
        return 0;
 | 
						|
 | 
						|
    typename ErrorInfo::value_type const * val = boost::get_error_info<ErrorInfo>( *ex );
 | 
						|
 | 
						|
    return val ? *val : 0;
 | 
						|
}
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
static void
 | 
						|
report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, va_list* args )
 | 
						|
{
 | 
						|
    static const int REPORT_ERROR_BUFFER_SIZE = 4096;
 | 
						|
    static char buf[REPORT_ERROR_BUFFER_SIZE];
 | 
						|
 | 
						|
    BOOST_TEST_VSNPRINTF( buf, sizeof(buf)-1, format, *args );
 | 
						|
    buf[sizeof(buf)-1] = 0;
 | 
						|
 | 
						|
    va_end( *args );
 | 
						|
 | 
						|
    BOOST_TEST_I_THROW(execution_exception( ec, buf, execution_exception::location( extract<throw_file>( be ),
 | 
						|
                                                                                    (size_t)extract<throw_line>( be ),
 | 
						|
                                                                                    extract<throw_function>( be ) ) ));
 | 
						|
}
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
static void
 | 
						|
report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, ... )
 | 
						|
{
 | 
						|
    va_list args;
 | 
						|
    va_start( args, format );
 | 
						|
 | 
						|
    report_error( ec, be, format, &args );
 | 
						|
}
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
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 );
 | 
						|
}
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
template<typename Tr,typename Functor>
 | 
						|
inline int
 | 
						|
do_invoke( Tr const& tr, Functor const& F )
 | 
						|
{
 | 
						|
    return tr ? (*tr)( F ) : F();
 | 
						|
}
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
struct fpe_except_guard {
 | 
						|
    explicit fpe_except_guard( unsigned detect_fpe )
 | 
						|
    : m_detect_fpe( detect_fpe )
 | 
						|
    {
 | 
						|
        // prepare fp exceptions control
 | 
						|
        m_previously_enabled = fpe::disable( fpe::BOOST_FPE_ALL );
 | 
						|
        if( m_previously_enabled != fpe::BOOST_FPE_INV && detect_fpe != fpe::BOOST_FPE_OFF )
 | 
						|
            fpe::enable( detect_fpe );
 | 
						|
    }
 | 
						|
    ~fpe_except_guard()
 | 
						|
    {
 | 
						|
        if( m_detect_fpe != fpe::BOOST_FPE_OFF )
 | 
						|
            fpe::disable( m_detect_fpe );
 | 
						|
        if( m_previously_enabled != fpe::BOOST_FPE_INV )
 | 
						|
            fpe::enable( m_previously_enabled );
 | 
						|
    }
 | 
						|
 | 
						|
    unsigned m_detect_fpe;
 | 
						|
    unsigned m_previously_enabled;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
// ************************************************************************** //
 | 
						|
// **************                  typeid_name                 ************** //
 | 
						|
// ************************************************************************** //
 | 
						|
 | 
						|
#if !defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
 | 
						|
template<typename T>
 | 
						|
std::string
 | 
						|
typeid_name( T const& t )
 | 
						|
{
 | 
						|
    return boost::core::demangle(typeid(t).name());
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
} // namespace detail
 | 
						|
 | 
						|
#if defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING)
 | 
						|
 | 
						|
// ************************************************************************** //
 | 
						|
// **************       Sigaction based signal handling        ************** //
 | 
						|
// ************************************************************************** //
 | 
						|
 | 
						|
namespace detail {
 | 
						|
 | 
						|
// ************************************************************************** //
 | 
						|
// **************    boost::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;
 | 
						|
 | 
						|
#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 occurred; 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 %d", m_sig_info->si_signo );
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
// ************************************************************************** //
 | 
						|
// **************         boost::detail::signal_action         ************** //
 | 
						|
// ************************************************************************** //
 | 
						|
 | 
						|
// Forward declaration
 | 
						|
extern "C" {
 | 
						|
static void boost_execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context );
 | 
						|
static void boost_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 ? &boost_execution_monitor_attaching_signal_handler
 | 
						|
                                            : &boost_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() );
 | 
						|
}
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
// ************************************************************************** //
 | 
						|
// **************        boost::detail::signal_handler         ************** //
 | 
						|
// ************************************************************************** //
 | 
						|
 | 
						|
class signal_handler {
 | 
						|
public:
 | 
						|
    // Constructor
 | 
						|
    explicit signal_handler( bool catch_system_errors, bool detect_fpe, unsigned 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;
 | 
						|
    unsigned                m_timeout;
 | 
						|
 | 
						|
    // Note: We intentionality do not catch SIGCHLD. Users have to deal with it themselves
 | 
						|
    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, bool detect_fpe, unsigned 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 , detect_fpe         , 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 )
 | 
						|
#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;
 | 
						|
    if( ::sigaltstack( &sigstk, 0 ) == -1 ) {
 | 
						|
        int error_n = errno;
 | 
						|
        std::cerr << "******** errors disabling the alternate stack:" << std::endl
 | 
						|
                  << "\t#error:" << error_n << std::endl
 | 
						|
                  << "\t" << std::strerror( error_n ) << std::endl;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    s_active_handler = m_prev_handler;
 | 
						|
}
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
// ************************************************************************** //
 | 
						|
// **************       execution_monitor_signal_handler       ************** //
 | 
						|
// ************************************************************************** //
 | 
						|
 | 
						|
extern "C" {
 | 
						|
 | 
						|
static void boost_execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context )
 | 
						|
{
 | 
						|
    signal_handler::sys_sig()( info, context );
 | 
						|
 | 
						|
    siglongjmp( signal_handler::jump_buffer(), sig );
 | 
						|
}
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
static void boost_execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context )
 | 
						|
{
 | 
						|
    if( !debug::attach_debugger( false ) )
 | 
						|
        boost_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( boost::function<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_catch_system_errors || (p_detect_fp_exceptions != fpe::BOOST_FPE_OFF),
 | 
						|
                                         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
 | 
						|
        BOOST_TEST_I_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 {
 | 
						|
 | 
						|
// ************************************************************************** //
 | 
						|
// **************    boost::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 id, _EXCEPTION_POINTERS* exps );
 | 
						|
 | 
						|
private:
 | 
						|
    // Data members
 | 
						|
    execution_monitor*  m_em;
 | 
						|
 | 
						|
    unsigned            m_se_id;
 | 
						|
    void*               m_fault_address;
 | 
						|
    bool                m_dir;
 | 
						|
};
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
#if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
 | 
						|
static void
 | 
						|
seh_catch_preventer( unsigned /* id */, _EXCEPTION_POINTERS* /* exps */ )
 | 
						|
{
 | 
						|
    throw;
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
int
 | 
						|
system_signal_exception::operator()( unsigned id, _EXCEPTION_POINTERS* exps )
 | 
						|
{
 | 
						|
    const unsigned MSFT_CPP_EXCEPT = 0xE06d7363; // EMSC
 | 
						|
 | 
						|
    // C++ exception - allow to go through
 | 
						|
    if( id == MSFT_CPP_EXCEPT )
 | 
						|
        return EXCEPTION_CONTINUE_SEARCH;
 | 
						|
 | 
						|
    // FPE detection is enabled, while system exception detection is not - check if this is actually FPE
 | 
						|
    if( !m_em->p_catch_system_errors ) {
 | 
						|
        if( !m_em->p_detect_fp_exceptions )
 | 
						|
            return EXCEPTION_CONTINUE_SEARCH;
 | 
						|
 | 
						|
        switch( id ) {
 | 
						|
        case EXCEPTION_FLT_DIVIDE_BY_ZERO:
 | 
						|
        case EXCEPTION_FLT_STACK_CHECK:
 | 
						|
        case EXCEPTION_FLT_DENORMAL_OPERAND:
 | 
						|
        case EXCEPTION_FLT_INEXACT_RESULT:
 | 
						|
        case EXCEPTION_FLT_OVERFLOW:
 | 
						|
        case EXCEPTION_FLT_UNDERFLOW:
 | 
						|
        case EXCEPTION_FLT_INVALID_OPERATION:
 | 
						|
        case STATUS_FLOAT_MULTIPLE_FAULTS:
 | 
						|
        case STATUS_FLOAT_MULTIPLE_TRAPS:
 | 
						|
            break;
 | 
						|
        default:
 | 
						|
            return EXCEPTION_CONTINUE_SEARCH;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if( !!m_em->p_auto_start_dbg && debug::attach_debugger( false ) ) {
 | 
						|
        m_em->p_catch_system_errors.value = false;
 | 
						|
#if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
 | 
						|
        _set_se_translator( &seh_catch_preventer );
 | 
						|
#endif
 | 
						|
        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;
 | 
						|
 | 
						|
    case EXCEPTION_FLT_INEXACT_RESULT:
 | 
						|
        detail::report_error( execution_exception::system_error,
 | 
						|
                              "result of a floating-point operation cannot be represented exactly" );
 | 
						|
        break;
 | 
						|
 | 
						|
    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 STATUS_FLOAT_MULTIPLE_FAULTS:
 | 
						|
        detail::report_error( execution_exception::system_error, "multiple floating point errors" );
 | 
						|
        break;
 | 
						|
 | 
						|
    case STATUS_FLOAT_MULTIPLE_TRAPS:
 | 
						|
        detail::report_error( execution_exception::system_error, "multiple floating point errors" );
 | 
						|
        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* )
 | 
						|
{
 | 
						|
    // write this way instead of switch to avoid unreachable statements
 | 
						|
    if( reportType == BOOST_TEST_CRT_ASSERT || reportType == BOOST_TEST_CRT_ERROR )
 | 
						|
        detail::report_error( reportType == BOOST_TEST_CRT_ASSERT ? execution_exception::user_error : execution_exception::system_error, userMessage );
 | 
						|
 | 
						|
    return 0;
 | 
						|
} // assert_reporting_function
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
void BOOST_TEST_CALL_DECL
 | 
						|
invalid_param_handler( wchar_t const* /* expr */,
 | 
						|
                       wchar_t const* /* func */,
 | 
						|
                       wchar_t const* /* file */,
 | 
						|
                       unsigned       /* line */,
 | 
						|
                       uintptr_t      /* reserved */)
 | 
						|
{
 | 
						|
    detail::report_error( execution_exception::user_error,
 | 
						|
                          "Invalid parameter detected by C runtime library" );
 | 
						|
}
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
} // namespace detail
 | 
						|
 | 
						|
// ************************************************************************** //
 | 
						|
// **************        execution_monitor::catch_signals      ************** //
 | 
						|
// ************************************************************************** //
 | 
						|
 | 
						|
int
 | 
						|
execution_monitor::catch_signals( boost::function<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 ) {
 | 
						|
        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 ) );
 | 
						|
    } else if( !p_detect_fp_exceptions ) {
 | 
						|
#if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
 | 
						|
        _set_se_translator( &detail::seh_catch_preventer );
 | 
						|
#endif
 | 
						|
    }
 | 
						|
 | 
						|
    detail::system_signal_exception SSE( this );
 | 
						|
 | 
						|
    int ret_val = 0;
 | 
						|
    // clang windows workaround: this not available in __finally scope
 | 
						|
    bool l_catch_system_errors = p_catch_system_errors;
 | 
						|
 | 
						|
    __try {
 | 
						|
        __try {
 | 
						|
            ret_val = detail::do_invoke( m_custom_translators, F );
 | 
						|
        }
 | 
						|
        __except( SSE( GetExceptionCode(), GetExceptionInformation() ) ) {
 | 
						|
            throw SSE;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    __finally {
 | 
						|
        if( l_catch_system_errors ) {
 | 
						|
            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( boost::function<int ()> const& F )
 | 
						|
{
 | 
						|
    return detail::do_invoke( m_custom_translators , F );
 | 
						|
}
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
#endif  // choose signal handler
 | 
						|
 | 
						|
// ************************************************************************** //
 | 
						|
// **************              execution_monitor               ************** //
 | 
						|
// ************************************************************************** //
 | 
						|
 | 
						|
execution_monitor::execution_monitor()
 | 
						|
: p_catch_system_errors( true )
 | 
						|
, p_auto_start_dbg( false )
 | 
						|
, p_timeout( 0 )
 | 
						|
, p_use_alt_stack( true )
 | 
						|
, p_detect_fp_exceptions( fpe::BOOST_FPE_OFF )
 | 
						|
{}
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
int
 | 
						|
execution_monitor::execute( boost::function<int ()> const& F )
 | 
						|
{
 | 
						|
    if( debug::under_debugger() )
 | 
						|
        p_catch_system_errors.value = false;
 | 
						|
 | 
						|
    BOOST_TEST_I_TRY {
 | 
						|
        detail::fpe_except_guard G( p_detect_fp_exceptions );
 | 
						|
        unit_test::ut_detail::ignore_unused_variable_warning( G );
 | 
						|
 | 
						|
        return catch_signals( F );
 | 
						|
    }
 | 
						|
 | 
						|
#ifndef BOOST_NO_EXCEPTIONS
 | 
						|
 | 
						|
    //  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
 | 
						|
#if defined(BOOST_NO_TYPEID) || defined(BOOST_NO_RTTI)
 | 
						|
#define CATCH_AND_REPORT_STD_EXCEPTION( ex_name )                           \
 | 
						|
    catch( ex_name const& ex )                                              \
 | 
						|
       { detail::report_error( execution_exception::cpp_exception_error,    \
 | 
						|
                          current_exception_cast<boost::exception const>(), \
 | 
						|
                          #ex_name ": %s", ex.what() ); }                   \
 | 
						|
/**/
 | 
						|
#else
 | 
						|
#define CATCH_AND_REPORT_STD_EXCEPTION( ex_name )                           \
 | 
						|
    catch( ex_name const& ex )                                              \
 | 
						|
        { detail::report_error( execution_exception::cpp_exception_error,   \
 | 
						|
                          current_exception_cast<boost::exception const>(), \
 | 
						|
                          "%s: %s", detail::typeid_name(ex).c_str(), ex.what() ); } \
 | 
						|
/**/
 | 
						|
#endif
 | 
						|
 | 
						|
    CATCH_AND_REPORT_STD_EXCEPTION( std::bad_alloc )
 | 
						|
 | 
						|
#if BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
 | 
						|
    CATCH_AND_REPORT_STD_EXCEPTION( std::bad_cast )
 | 
						|
    CATCH_AND_REPORT_STD_EXCEPTION( std::bad_typeid )
 | 
						|
#else
 | 
						|
    CATCH_AND_REPORT_STD_EXCEPTION( std::bad_cast )
 | 
						|
    CATCH_AND_REPORT_STD_EXCEPTION( std::bad_typeid )
 | 
						|
#endif
 | 
						|
 | 
						|
    CATCH_AND_REPORT_STD_EXCEPTION( std::bad_exception )
 | 
						|
    CATCH_AND_REPORT_STD_EXCEPTION( std::domain_error )
 | 
						|
    CATCH_AND_REPORT_STD_EXCEPTION( std::invalid_argument )
 | 
						|
    CATCH_AND_REPORT_STD_EXCEPTION( std::length_error )
 | 
						|
    CATCH_AND_REPORT_STD_EXCEPTION( std::out_of_range )
 | 
						|
    CATCH_AND_REPORT_STD_EXCEPTION( std::range_error )
 | 
						|
    CATCH_AND_REPORT_STD_EXCEPTION( std::overflow_error )
 | 
						|
    CATCH_AND_REPORT_STD_EXCEPTION( std::underflow_error )
 | 
						|
    CATCH_AND_REPORT_STD_EXCEPTION( std::logic_error )
 | 
						|
    CATCH_AND_REPORT_STD_EXCEPTION( std::runtime_error )
 | 
						|
    CATCH_AND_REPORT_STD_EXCEPTION( std::exception )
 | 
						|
#undef CATCH_AND_REPORT_STD_EXCEPTION
 | 
						|
 | 
						|
    catch( boost::exception const& ex )
 | 
						|
      { detail::report_error( execution_exception::cpp_exception_error,
 | 
						|
                              &ex,
 | 
						|
#if defined(BOOST_NO_TYPEID) || defined(BOOST_NO_RTTI)
 | 
						|
                              "unknown boost::exception" ); }
 | 
						|
#else
 | 
						|
                              typeid(ex).name()          ); }
 | 
						|
#endif
 | 
						|
 | 
						|
    // 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, 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" ); }
 | 
						|
 | 
						|
#endif // !BOOST_NO_EXCEPTION
 | 
						|
 | 
						|
    return 0;  // never reached; supplied to quiet compiler warnings
 | 
						|
} // execute
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
namespace detail {
 | 
						|
 | 
						|
struct forward {
 | 
						|
    explicit    forward( boost::function<void ()> const& F ) : m_F( F ) {}
 | 
						|
 | 
						|
    int         operator()() { m_F(); return 0; }
 | 
						|
 | 
						|
    boost::function<void ()> const& m_F;
 | 
						|
};
 | 
						|
 | 
						|
} // namespace detail
 | 
						|
void
 | 
						|
execution_monitor::vexecute( boost::function<void ()> const& F )
 | 
						|
{
 | 
						|
    execute( detail::forward( F ) );
 | 
						|
}
 | 
						|
 | 
						|
// ************************************************************************** //
 | 
						|
// **************                  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 )
 | 
						|
{}
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
// ************************************************************************** //
 | 
						|
// **************Floating point exception management interface ************** //
 | 
						|
// ************************************************************************** //
 | 
						|
 | 
						|
namespace fpe {
 | 
						|
 | 
						|
unsigned
 | 
						|
enable( unsigned mask )
 | 
						|
{
 | 
						|
    boost::ignore_unused(mask);
 | 
						|
 | 
						|
#if defined(UNDER_CE)
 | 
						|
    /* Not Implemented in Windows CE */
 | 
						|
    return BOOST_FPE_OFF;
 | 
						|
#elif defined(BOOST_SEH_BASED_SIGNAL_HANDLING)
 | 
						|
    _clearfp();
 | 
						|
 | 
						|
#if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
 | 
						|
    unsigned old_cw = ::_controlfp( 0, 0 );
 | 
						|
    ::_controlfp( old_cw & ~mask, BOOST_FPE_ALL );
 | 
						|
#else
 | 
						|
    unsigned old_cw;
 | 
						|
    if( ::_controlfp_s( &old_cw, 0, 0 ) != 0 )
 | 
						|
        return BOOST_FPE_INV;
 | 
						|
 | 
						|
    // Set the control word
 | 
						|
    if( ::_controlfp_s( 0, old_cw & ~mask, BOOST_FPE_ALL ) != 0 )
 | 
						|
        return BOOST_FPE_INV;
 | 
						|
#endif
 | 
						|
 | 
						|
    return ~old_cw & BOOST_FPE_ALL;
 | 
						|
#elif defined(__GLIBC__) && defined(__USE_GNU)
 | 
						|
    if (BOOST_FPE_ALL == BOOST_FPE_OFF)
 | 
						|
        /* Not Implemented */
 | 
						|
        return BOOST_FPE_OFF;
 | 
						|
    feclearexcept(BOOST_FPE_ALL);
 | 
						|
    int res = feenableexcept( mask );
 | 
						|
    return res == -1 ? (unsigned)BOOST_FPE_INV : (unsigned)res;
 | 
						|
#else
 | 
						|
    /* Not Implemented  */
 | 
						|
    return BOOST_FPE_OFF;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
unsigned
 | 
						|
disable( unsigned mask )
 | 
						|
{
 | 
						|
    boost::ignore_unused(mask);
 | 
						|
 | 
						|
#if defined(UNDER_CE)
 | 
						|
    /* Not Implemented in Windows CE */
 | 
						|
    return BOOST_FPE_INV;
 | 
						|
#elif defined(BOOST_SEH_BASED_SIGNAL_HANDLING)
 | 
						|
    _clearfp();
 | 
						|
 | 
						|
#if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
 | 
						|
    unsigned old_cw = ::_controlfp( 0, 0 );
 | 
						|
    ::_controlfp( old_cw | mask, BOOST_FPE_ALL );
 | 
						|
#else
 | 
						|
    unsigned old_cw;
 | 
						|
    if( ::_controlfp_s( &old_cw, 0, 0 ) != 0 )
 | 
						|
        return BOOST_FPE_INV;
 | 
						|
 | 
						|
    // Set the control word
 | 
						|
    if( ::_controlfp_s( 0, old_cw | mask, BOOST_FPE_ALL ) != 0 )
 | 
						|
        return BOOST_FPE_INV;
 | 
						|
#endif
 | 
						|
 | 
						|
    return ~old_cw & BOOST_FPE_ALL;
 | 
						|
#elif defined(__GLIBC__) && defined(__USE_GNU)
 | 
						|
    if (BOOST_FPE_ALL == BOOST_FPE_OFF)
 | 
						|
        /* Not Implemented */
 | 
						|
        return BOOST_FPE_INV;
 | 
						|
    feclearexcept(BOOST_FPE_ALL);
 | 
						|
    int res = fedisableexcept( mask );
 | 
						|
    return res == -1 ? (unsigned)BOOST_FPE_INV : (unsigned)res;
 | 
						|
#else
 | 
						|
    /* Not Implemented */
 | 
						|
    return BOOST_FPE_INV;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
//____________________________________________________________________________//
 | 
						|
 | 
						|
} // namespace fpe
 | 
						|
 | 
						|
} // namespace boost
 | 
						|
 | 
						|
#include <boost/test/detail/enable_warnings.hpp>
 | 
						|
 | 
						|
#endif // BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER
 |