Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:00:59

0001 //  (C) Copyright Gennadiy Rozental 2001.
0002 //  (C) Copyright Beman Dawes and Ullrich Koethe 1995-2001.
0003 //  Use, modification, and distribution are subject to the
0004 //  Boost Software License, Version 1.0. (See accompanying file
0005 //  http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 //  See http://www.boost.org/libs/test for the library home page.
0008 //
0009 ///  @file
0010 ///  Provides execution monitor implementation for all supported
0011 ///  configurations, including Microsoft structured exception based, unix signals
0012 ///  based and special workarounds for borland
0013 ///
0014 ///  Note that when testing requirements or user wishes preclude use of this
0015 ///  file as a separate compilation unit, it may be included as a header file.
0016 ///
0017 ///  Header dependencies are deliberately restricted to reduce coupling to other
0018 ///  boost libraries.
0019 // ***************************************************************************
0020 
0021 #ifndef BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER
0022 #define BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER
0023 
0024 // Boost.Test
0025 #include <boost/test/detail/config.hpp>
0026 #include <boost/test/detail/throw_exception.hpp>
0027 #include <boost/test/execution_monitor.hpp>
0028 #include <boost/test/debug.hpp>
0029 
0030 // Boost
0031 #include <boost/cstdlib.hpp>    // for exit codes
0032 #include <boost/config.hpp>     // for workarounds
0033 #include <boost/core/ignore_unused.hpp> // for ignore_unused
0034 #ifndef BOOST_NO_EXCEPTIONS
0035 #include <boost/exception/get_error_info.hpp> // for get_error_info
0036 #include <boost/exception/current_exception_cast.hpp> // for current_exception_cast
0037 #include <boost/exception/diagnostic_information.hpp>
0038 #endif
0039 
0040 // STL
0041 #include <string>               // for std::string
0042 #include <new>                  // for std::bad_alloc
0043 #include <typeinfo>             // for std::bad_cast, std::bad_typeid
0044 #include <exception>            // for std::exception, std::bad_exception
0045 #include <stdexcept>            // for std exception hierarchy
0046 #include <cstring>              // for C string API
0047 #include <cassert>              // for assert
0048 #include <cstddef>              // for NULL
0049 #include <cstdio>               // for vsnprintf
0050 #include <stdio.h>
0051 #include <cstdarg>              // for varargs
0052 #include <stdarg.h>
0053 #include <cmath>                // for ceil
0054 
0055 #include <iostream>              // for varargs
0056 
0057 #ifdef BOOST_NO_STDC_NAMESPACE
0058 namespace std { using ::strerror; using ::strlen; using ::strncat; using ::ceil; }
0059 #endif
0060 
0061 // to use vsnprintf
0062 #if defined(__SUNPRO_CC) || defined(__SunOS) || defined(__QNXNTO__) || defined(__VXWORKS__)
0063 using std::va_list;
0064 #endif
0065 
0066 #if defined(__VXWORKS__)
0067 # define BOOST_TEST_LIMITED_SIGNAL_DETAILS
0068 #endif
0069 
0070 #ifdef BOOST_SEH_BASED_SIGNAL_HANDLING
0071 
0072 # if !defined(_WIN32_WINNT) // WinXP
0073 #   define _WIN32_WINNT  0x0501
0074 # endif
0075 
0076 #  include <windows.h>
0077 
0078 #  if defined(__MWERKS__) || (defined(_MSC_VER) && !defined(UNDER_CE))
0079 #    include <eh.h>
0080 #  endif
0081 
0082 #  if defined(BOOST_BORLANDC) && BOOST_BORLANDC >= 0x560 || defined(__MWERKS__)
0083 #    include <stdint.h>
0084 #  endif
0085 
0086 #  if defined(BOOST_BORLANDC) && BOOST_BORLANDC < 0x560
0087     typedef unsigned uintptr_t;
0088 #  endif
0089 
0090 #  if defined(UNDER_CE) && BOOST_WORKAROUND(_MSC_VER,  < 1500 )
0091    typedef void* uintptr_t;
0092 #  elif defined(UNDER_CE)
0093 #  include <crtdefs.h>
0094 #  endif
0095 
0096 #  if !defined(NDEBUG) && defined(_MSC_VER) && !defined(UNDER_CE)
0097 #    include <crtdbg.h>
0098 #    define BOOST_TEST_CRT_HOOK_TYPE    _CRT_REPORT_HOOK
0099 #    define BOOST_TEST_CRT_ASSERT       _CRT_ASSERT
0100 #    define BOOST_TEST_CRT_ERROR        _CRT_ERROR
0101 #    define BOOST_TEST_CRT_SET_HOOK(H)  _CrtSetReportHook(H)
0102 #  else
0103 #    define BOOST_TEST_CRT_HOOK_TYPE    void*
0104 #    define BOOST_TEST_CRT_ASSERT       2
0105 #    define BOOST_TEST_CRT_ERROR        1
0106 #    define BOOST_TEST_CRT_SET_HOOK(H)  (void*)(H)
0107 #  endif
0108 
0109 #  if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) /* WinXP */
0110 #    define BOOST_TEST_WIN32_WAITABLE_TIMERS
0111 #  endif
0112 
0113 #  if (!BOOST_WORKAROUND(_MSC_VER,  >= 1400 ) && \
0114       !defined(BOOST_COMO)) || defined(UNDER_CE)
0115 
0116 typedef void* _invalid_parameter_handler;
0117 
0118 inline _invalid_parameter_handler
0119 _set_invalid_parameter_handler( _invalid_parameter_handler arg )
0120 {
0121     return arg;
0122 }
0123 
0124 #  endif
0125 
0126 #  if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0564)) || defined(UNDER_CE)
0127 
0128 namespace { void _set_se_translator( void* ) {} }
0129 
0130 #  endif
0131 
0132 #elif defined(BOOST_HAS_SIGACTION)
0133 
0134 #  define BOOST_SIGACTION_BASED_SIGNAL_HANDLING
0135 
0136 #  include <unistd.h>
0137 #  include <signal.h>
0138 #  include <setjmp.h>
0139 
0140 #  if defined(__FreeBSD__)
0141 
0142 #    include <osreldate.h>
0143 
0144 #    ifndef SIGPOLL
0145 #      define SIGPOLL SIGIO
0146 #    endif
0147 
0148 #    if (__FreeBSD_version < 70100)
0149 
0150 #      define ILL_ILLADR 0 // ILL_RESAD_FAULT
0151 #      define ILL_PRVOPC ILL_PRIVIN_FAULT
0152 #      define ILL_ILLOPN 2 // ILL_RESOP_FAULT
0153 #      define ILL_COPROC ILL_FPOP_FAULT
0154 
0155 #      define BOOST_TEST_LIMITED_SIGNAL_DETAILS
0156 
0157 #    endif
0158 #  endif
0159 
0160 #  if defined(__ANDROID__)
0161 #    include <android/api-level.h>
0162 #  endif
0163 
0164 // documentation of BOOST_TEST_DISABLE_ALT_STACK in execution_monitor.hpp
0165 #  if !defined(__CYGWIN__) && !defined(__QNXNTO__) && !defined(__bgq__) && \
0166    (!defined(__ANDROID__) || __ANDROID_API__ >= 8) && !defined(__wasm__) && \
0167    !defined(BOOST_TEST_DISABLE_ALT_STACK)
0168 #    define BOOST_TEST_USE_ALT_STACK
0169 #  endif
0170 
0171 #  if defined(SIGPOLL) && !defined(__CYGWIN__)                              && \
0172       !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))  && \
0173       !defined(__NetBSD__)                                                  && \
0174       !defined(__QNXNTO__)
0175 #    define BOOST_TEST_CATCH_SIGPOLL
0176 #  endif
0177 
0178 #  ifdef BOOST_TEST_USE_ALT_STACK
0179 #    define BOOST_TEST_ALT_STACK_SIZE SIGSTKSZ
0180 #  endif
0181 
0182 
0183 #else
0184 
0185 #  define BOOST_NO_SIGNAL_HANDLING
0186 
0187 #endif
0188 
0189 #ifndef UNDER_CE
0190 #include <errno.h>
0191 #endif
0192 
0193 #if !defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
0194 #  include <boost/core/demangle.hpp>
0195 #endif
0196 
0197 #if (!defined(BOOST_MSSTL_VERSION) || (BOOST_MSSTL_VERSION >= 120)) && (!defined(__GLIBC__) || ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 2))))
0198 // glibc 2.2 - 2.17 required __STDC_FORMAT_MACROS to be defined for use of PRIxPTR
0199 #  if defined(__GLIBC__) && !((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 18)))
0200 #    ifndef __STDC_FORMAT_MACROS
0201 #      define __STDC_FORMAT_MACROS 1
0202 #      define BOOST_TEST_DEFINED_STDC_FORMAT_MACROS
0203 #    endif
0204 #  endif
0205 #  include <inttypes.h>
0206 #  define BOOST_TEST_PRIxPTR PRIxPTR
0207 #  ifdef BOOST_TEST_DEFINED_STDC_FORMAT_MACROS
0208 #    undef __STDC_FORMAT_MACROS
0209 #  endif
0210 #else
0211 #  define BOOST_TEST_PRIxPTR "08lx"
0212 #endif
0213 
0214 #include <boost/test/detail/suppress_warnings.hpp>
0215 
0216 //____________________________________________________________________________//
0217 
0218 namespace boost {
0219 
0220 // ************************************************************************** //
0221 // **************                 throw_exception              ************** //
0222 // ************************************************************************** //
0223 
0224 #ifdef BOOST_NO_EXCEPTIONS
0225 void throw_exception( std::exception const & e ) { abort(); }
0226 #endif
0227 
0228 // ************************************************************************** //
0229 // **************                  report_error                ************** //
0230 // ************************************************************************** //
0231 
0232 namespace detail {
0233 
0234 #ifdef BOOST_BORLANDC
0235 #  define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) std::vsnprintf( (a1), (a2), (a3), (a4) )
0236 #elif BOOST_WORKAROUND(_MSC_VER, <= 1310) || \
0237       BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3000)) || \
0238       defined(UNDER_CE) || \
0239       (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
0240 #  define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) _vsnprintf( (a1), (a2), (a3), (a4) )
0241 #else
0242 #  define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) vsnprintf( (a1), (a2), (a3), (a4) )
0243 #endif
0244 
0245 
0246 /* checks the printf formatting by adding a decorator to the function */
0247 #if __GNUC__ >= 3 || defined(BOOST_EMBTC)
0248 #define BOOST_TEST_PRINTF_ATTRIBUTE_CHECK(x, y) __attribute__((__format__ (__printf__, x, y)))
0249 #else
0250 #define BOOST_TEST_PRINTF_ATTRIBUTE_CHECK(x, y)
0251 #endif
0252 
0253 #ifndef BOOST_NO_EXCEPTIONS
0254 
0255 template <typename ErrorInfo>
0256 typename ErrorInfo::value_type
0257 extract( boost::exception const* ex )
0258 {
0259     if( !ex )
0260         return 0;
0261 
0262     typename ErrorInfo::value_type const * val = boost::get_error_info<ErrorInfo>( *ex );
0263 
0264     return val ? *val : 0;
0265 }
0266 
0267 //____________________________________________________________________________//
0268 
0269 static void
0270 BOOST_TEST_PRINTF_ATTRIBUTE_CHECK(3, 0)
0271 report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, va_list* args )
0272 {
0273     static const int REPORT_ERROR_BUFFER_SIZE = 4096;
0274     static char buf[REPORT_ERROR_BUFFER_SIZE];
0275 
0276     BOOST_TEST_VSNPRINTF( buf, sizeof(buf)-1, format, *args );
0277     buf[sizeof(buf)-1] = 0;
0278 
0279     va_end( *args );
0280 
0281     BOOST_TEST_I_THROW(execution_exception( ec, buf, execution_exception::location( extract<throw_file>( be ),
0282                                                                                     (size_t)extract<throw_line>( be ),
0283                                                                                     extract<throw_function>( be ) ) ));
0284 }
0285 
0286 //____________________________________________________________________________//
0287 
0288 static void
0289 BOOST_TEST_PRINTF_ATTRIBUTE_CHECK(3, 4)
0290 report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, ... )
0291 {
0292     va_list args;
0293     va_start( args, format );
0294 
0295     report_error( ec, be, format, &args );
0296 }
0297 
0298 #endif
0299 
0300 //____________________________________________________________________________//
0301 
0302 static void
0303 BOOST_TEST_PRINTF_ATTRIBUTE_CHECK(2, 3)
0304 report_error( execution_exception::error_code ec, char const* format, ... )
0305 {
0306     va_list args;
0307     va_start( args, format );
0308 
0309     report_error( ec, 0, format, &args );
0310 }
0311 
0312 //____________________________________________________________________________//
0313 
0314 template<typename Tr,typename Functor>
0315 inline int
0316 do_invoke( Tr const& tr, Functor const& F )
0317 {
0318     return tr ? (*tr)( F ) : F();
0319 }
0320 
0321 //____________________________________________________________________________//
0322 
0323 struct fpe_except_guard {
0324     explicit fpe_except_guard( unsigned detect_fpe )
0325     : m_detect_fpe( detect_fpe )
0326     {
0327         // prepare fp exceptions control
0328         m_previously_enabled = fpe::disable( fpe::BOOST_FPE_ALL );
0329         if( m_previously_enabled != fpe::BOOST_FPE_INV && detect_fpe != fpe::BOOST_FPE_OFF )
0330             fpe::enable( detect_fpe );
0331     }
0332     ~fpe_except_guard()
0333     {
0334         if( m_detect_fpe != fpe::BOOST_FPE_OFF )
0335             fpe::disable( m_detect_fpe );
0336         if( m_previously_enabled != fpe::BOOST_FPE_INV )
0337             fpe::enable( m_previously_enabled );
0338     }
0339 
0340     unsigned m_detect_fpe;
0341     unsigned m_previously_enabled;
0342 };
0343 
0344 
0345 // ************************************************************************** //
0346 // **************                  typeid_name                 ************** //
0347 // ************************************************************************** //
0348 
0349 #if !defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
0350 template<typename T>
0351 std::string
0352 typeid_name( T const& t )
0353 {
0354     return boost::core::demangle(typeid(t).name());
0355 }
0356 #endif
0357 
0358 } // namespace detail
0359 
0360 #if defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING)
0361 
0362 // ************************************************************************** //
0363 // **************       Sigaction based signal handling        ************** //
0364 // ************************************************************************** //
0365 
0366 namespace detail {
0367 
0368 // ************************************************************************** //
0369 // **************    boost::detail::system_signal_exception    ************** //
0370 // ************************************************************************** //
0371 
0372 class system_signal_exception {
0373 public:
0374     // Constructor
0375     system_signal_exception()
0376     : m_sig_info( 0 )
0377     , m_context( 0 )
0378     {}
0379 
0380     // Access methods
0381     void        operator()( siginfo_t* i, void* c )
0382     {
0383         m_sig_info  = i;
0384         m_context   = c;
0385     }
0386     void        report() const;
0387 
0388 private:
0389     // Data members
0390     siginfo_t*  m_sig_info; // system signal detailed info
0391     void*       m_context;  // signal context
0392 };
0393 
0394 //____________________________________________________________________________//
0395 
0396 void
0397 system_signal_exception::report() const
0398 {
0399     if( !m_sig_info )
0400         return; // no error actually occur?
0401 
0402     switch( m_sig_info->si_code ) {
0403 #ifdef __VXWORKS__
0404 // a bit of a hack to adapt code to small m_sig_info VxWorks uses
0405 #define si_addr si_value.sival_int
0406 #define si_band si_value.sival_int
0407 #else
0408     case SI_USER:
0409         report_error( execution_exception::system_error,
0410                       "signal: generated by kill() (or family); uid=%d; pid=%d",
0411                       (int)m_sig_info->si_uid, (int)m_sig_info->si_pid );
0412         break;
0413 #endif
0414     case SI_QUEUE:
0415         report_error( execution_exception::system_error,
0416                       "signal: sent by sigqueue()" );
0417         break;
0418     case SI_TIMER:
0419         report_error( execution_exception::system_error,
0420                       "signal: the expiration of a timer set by timer_settimer()" );
0421         break;
0422 // OpenBSD was missing SI_ASYNCIO and SI_MESGQ
0423 #ifdef SI_ASYNCIO
0424     case SI_ASYNCIO:
0425         report_error( execution_exception::system_error,
0426                       "signal: generated by the completion of an asynchronous I/O request" );
0427         break;
0428 #endif
0429 #ifdef SI_MESGQ
0430     case SI_MESGQ:
0431         report_error( execution_exception::system_error,
0432                       "signal: generated by the the arrival of a message on an empty message queue" );
0433         break;
0434 #endif
0435     default:
0436         break;
0437     }
0438 
0439     switch( m_sig_info->si_signo ) {
0440     case SIGILL:
0441         switch( m_sig_info->si_code ) {
0442 #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
0443         case ILL_ILLOPC:
0444             report_error( execution_exception::system_fatal_error,
0445                           "signal: illegal opcode; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
0446                           (uintptr_t) m_sig_info->si_addr );
0447             break;
0448         case ILL_ILLTRP:
0449             report_error( execution_exception::system_fatal_error,
0450                           "signal: illegal trap; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
0451                           (uintptr_t) m_sig_info->si_addr );
0452             break;
0453         case ILL_PRVREG:
0454             report_error( execution_exception::system_fatal_error,
0455                           "signal: privileged register; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
0456                           (uintptr_t) m_sig_info->si_addr );
0457             break;
0458         case ILL_BADSTK:
0459             report_error( execution_exception::system_fatal_error,
0460                           "signal: internal stack error; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
0461                           (uintptr_t) m_sig_info->si_addr );
0462             break;
0463 #endif
0464         case ILL_ILLOPN:
0465             report_error( execution_exception::system_fatal_error,
0466                           "signal: illegal operand; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
0467                           (uintptr_t) m_sig_info->si_addr );
0468             break;
0469         case ILL_ILLADR:
0470             report_error( execution_exception::system_fatal_error,
0471                           "signal: illegal addressing mode; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
0472                           (uintptr_t) m_sig_info->si_addr );
0473             break;
0474         case ILL_PRVOPC:
0475             report_error( execution_exception::system_fatal_error,
0476                           "signal: privileged opcode; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
0477                           (uintptr_t) m_sig_info->si_addr );
0478             break;
0479         case ILL_COPROC:
0480             report_error( execution_exception::system_fatal_error,
0481                           "signal: co-processor error; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
0482                           (uintptr_t) m_sig_info->si_addr );
0483             break;
0484         default:
0485             report_error( execution_exception::system_fatal_error,
0486                           "signal: SIGILL, si_code: %d (illegal instruction; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR ")",
0487                           m_sig_info->si_code, (uintptr_t) m_sig_info->si_addr );
0488             break;
0489         }
0490         break;
0491 
0492     case SIGFPE:
0493         switch( m_sig_info->si_code ) {
0494         case FPE_INTDIV:
0495             report_error( execution_exception::system_error,
0496                           "signal: integer divide by zero; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
0497                           (uintptr_t) m_sig_info->si_addr );
0498             break;
0499         case FPE_INTOVF:
0500             report_error( execution_exception::system_error,
0501                           "signal: integer overflow; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
0502                           (uintptr_t) m_sig_info->si_addr );
0503             break;
0504         case FPE_FLTDIV:
0505             report_error( execution_exception::system_error,
0506                           "signal: floating point divide by zero; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
0507                           (uintptr_t) m_sig_info->si_addr );
0508             break;
0509         case FPE_FLTOVF:
0510             report_error( execution_exception::system_error,
0511                           "signal: floating point overflow; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
0512                           (uintptr_t) m_sig_info->si_addr );
0513             break;
0514         case FPE_FLTUND:
0515             report_error( execution_exception::system_error,
0516                           "signal: floating point underflow; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
0517                           (uintptr_t) m_sig_info->si_addr );
0518             break;
0519         case FPE_FLTRES:
0520             report_error( execution_exception::system_error,
0521                           "signal: floating point inexact result; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
0522                           (uintptr_t) m_sig_info->si_addr );
0523             break;
0524         case FPE_FLTINV:
0525             report_error( execution_exception::system_error,
0526                           "signal: invalid floating point operation; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
0527                           (uintptr_t) m_sig_info->si_addr );
0528             break;
0529         case FPE_FLTSUB:
0530             report_error( execution_exception::system_error,
0531                           "signal: subscript out of range; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
0532                           (uintptr_t) m_sig_info->si_addr );
0533             break;
0534         default:
0535             report_error( execution_exception::system_error,
0536                           "signal: SIGFPE, si_code: %d (errnoneous arithmetic operations; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR ")",
0537                           m_sig_info->si_code, (uintptr_t) m_sig_info->si_addr );
0538             break;
0539         }
0540         break;
0541 
0542     case SIGSEGV:
0543         switch( m_sig_info->si_code ) {
0544 #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
0545         case SEGV_MAPERR:
0546             report_error( execution_exception::system_fatal_error,
0547                           "memory access violation at address: 0x%" BOOST_TEST_PRIxPTR ": no mapping at fault address",
0548                           (uintptr_t) m_sig_info->si_addr );
0549             break;
0550         case SEGV_ACCERR:
0551             report_error( execution_exception::system_fatal_error,
0552                           "memory access violation at address: 0x%" BOOST_TEST_PRIxPTR ": invalid permissions",
0553                           (uintptr_t) m_sig_info->si_addr );
0554             break;
0555 #endif
0556         default:
0557             report_error( execution_exception::system_fatal_error,
0558                           "signal: SIGSEGV, si_code: %d (memory access violation at address: 0x%" BOOST_TEST_PRIxPTR ")",
0559                           m_sig_info->si_code, (uintptr_t) m_sig_info->si_addr );
0560             break;
0561         }
0562         break;
0563 
0564     case SIGBUS:
0565         switch( m_sig_info->si_code ) {
0566 #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
0567         case BUS_ADRALN:
0568             report_error( execution_exception::system_fatal_error,
0569                           "memory access violation at address: 0x%" BOOST_TEST_PRIxPTR ": invalid address alignment",
0570                           (uintptr_t) m_sig_info->si_addr );
0571             break;
0572         case BUS_ADRERR:
0573             report_error( execution_exception::system_fatal_error,
0574                           "memory access violation at address: 0x%" BOOST_TEST_PRIxPTR ": non-existent physical address",
0575                           (uintptr_t) m_sig_info->si_addr );
0576             break;
0577         case BUS_OBJERR:
0578             report_error( execution_exception::system_fatal_error,
0579                           "memory access violation at address: 0x%" BOOST_TEST_PRIxPTR ": object specific hardware error",
0580                           (uintptr_t) m_sig_info->si_addr );
0581             break;
0582 #endif
0583         default:
0584             report_error( execution_exception::system_fatal_error,
0585                           "signal: SIGSEGV, si_code: %d (memory access violation at address: 0x%" BOOST_TEST_PRIxPTR ")",
0586                           m_sig_info->si_code, (uintptr_t) m_sig_info->si_addr );
0587             break;
0588         }
0589         break;
0590 
0591 #if defined(BOOST_TEST_CATCH_SIGPOLL)
0592 
0593     case SIGPOLL:
0594         switch( m_sig_info->si_code ) {
0595 #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
0596         case POLL_IN:
0597             report_error( execution_exception::system_error,
0598                           "data input available; band event %d",
0599                           (int)m_sig_info->si_band );
0600             break;
0601         case POLL_OUT:
0602             report_error( execution_exception::system_error,
0603                           "output buffers available; band event %d",
0604                           (int)m_sig_info->si_band );
0605             break;
0606         case POLL_MSG:
0607             report_error( execution_exception::system_error,
0608                           "input message available; band event %d",
0609                           (int)m_sig_info->si_band );
0610             break;
0611         case POLL_ERR:
0612             report_error( execution_exception::system_error,
0613                           "i/o error; band event %d",
0614                           (int)m_sig_info->si_band );
0615             break;
0616         case POLL_PRI:
0617             report_error( execution_exception::system_error,
0618                           "high priority input available; band event %d",
0619                           (int)m_sig_info->si_band );
0620             break;
0621 #if defined(POLL_ERR) && defined(POLL_HUP) && (POLL_ERR - POLL_HUP)
0622         case POLL_HUP:
0623             report_error( execution_exception::system_error,
0624                           "device disconnected; band event %d",
0625                           (int)m_sig_info->si_band );
0626             break;
0627 #endif
0628 #endif
0629         default:
0630             report_error( execution_exception::system_error,
0631                           "signal: SIGPOLL, si_code: %d (asynchronous I/O event occurred; band event %d)",
0632                           m_sig_info->si_code, (int)m_sig_info->si_band );
0633             break;
0634         }
0635         break;
0636 
0637 #endif
0638 
0639     case SIGABRT:
0640         report_error( execution_exception::system_error,
0641                       "signal: SIGABRT (application abort requested)" );
0642         break;
0643 
0644     case SIGALRM:
0645         report_error( execution_exception::timeout_error,
0646                       "signal: SIGALRM (timeout while executing function)" );
0647         break;
0648 
0649     default:
0650         report_error( execution_exception::system_error,
0651                       "unrecognized signal %d", m_sig_info->si_signo );
0652     }
0653 }
0654 
0655 //____________________________________________________________________________//
0656 
0657 // ************************************************************************** //
0658 // **************         boost::detail::signal_action         ************** //
0659 // ************************************************************************** //
0660 
0661 // Forward declaration
0662 extern "C" {
0663 static void boost_execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context );
0664 static void boost_execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context );
0665 }
0666 
0667 class signal_action {
0668     typedef struct sigaction* sigaction_ptr;
0669 public:
0670     //Constructor
0671     signal_action();
0672     signal_action( int sig, bool install, bool attach_dbg, char* alt_stack );
0673     ~signal_action();
0674 
0675 private:
0676     // Data members
0677     int                 m_sig;
0678     bool                m_installed;
0679     struct sigaction    m_new_action;
0680     struct sigaction    m_old_action;
0681 };
0682 
0683 //____________________________________________________________________________//
0684 
0685 signal_action::signal_action()
0686 : m_installed( false )
0687 {}
0688 
0689 //____________________________________________________________________________//
0690 
0691 signal_action::signal_action( int sig, bool install, bool attach_dbg, char* alt_stack )
0692 : m_sig( sig )
0693 , m_installed( install )
0694 {
0695     if( !install )
0696         return;
0697 
0698     std::memset( &m_new_action, 0, sizeof(struct sigaction) );
0699 
0700     BOOST_TEST_SYS_ASSERT( ::sigaction( m_sig , sigaction_ptr(), &m_new_action ) != -1 );
0701 
0702     if( m_new_action.sa_sigaction || m_new_action.sa_handler ) {
0703         m_installed = false;
0704         return;
0705     }
0706 
0707     m_new_action.sa_flags     |= SA_SIGINFO;
0708     m_new_action.sa_sigaction  = attach_dbg ? &boost_execution_monitor_attaching_signal_handler
0709                                             : &boost_execution_monitor_jumping_signal_handler;
0710     BOOST_TEST_SYS_ASSERT( sigemptyset( &m_new_action.sa_mask ) != -1 );
0711 
0712 #ifdef BOOST_TEST_USE_ALT_STACK
0713     if( alt_stack )
0714         m_new_action.sa_flags |= SA_ONSTACK;
0715 #endif
0716 
0717     BOOST_TEST_SYS_ASSERT( ::sigaction( m_sig, &m_new_action, &m_old_action ) != -1 );
0718 }
0719 
0720 //____________________________________________________________________________//
0721 
0722 signal_action::~signal_action()
0723 {
0724     if( m_installed )
0725         ::sigaction( m_sig, &m_old_action , sigaction_ptr() );
0726 }
0727 
0728 //____________________________________________________________________________//
0729 
0730 // ************************************************************************** //
0731 // **************        boost::detail::signal_handler         ************** //
0732 // ************************************************************************** //
0733 
0734 class signal_handler {
0735 public:
0736     // Constructor
0737     explicit signal_handler( bool catch_system_errors,
0738                              bool detect_fpe,
0739                              unsigned long int timeout_microseconds,
0740                              bool attach_dbg,
0741                              char* alt_stack );
0742 
0743     // Destructor
0744     ~signal_handler();
0745 
0746     // access methods
0747     static sigjmp_buf&      jump_buffer()
0748     {
0749         assert( !!s_active_handler );
0750 
0751         return s_active_handler->m_sigjmp_buf;
0752     }
0753 
0754     static system_signal_exception&  sys_sig()
0755     {
0756         assert( !!s_active_handler );
0757 
0758         return s_active_handler->m_sys_sig;
0759     }
0760 
0761 private:
0762     // Data members
0763     signal_handler*         m_prev_handler;
0764     unsigned long int       m_timeout_microseconds;
0765 
0766     // Note: We intentionality do not catch SIGCHLD. Users have to deal with it themselves
0767     signal_action           m_ILL_action;
0768     signal_action           m_FPE_action;
0769     signal_action           m_SEGV_action;
0770     signal_action           m_BUS_action;
0771     signal_action           m_CHLD_action;
0772     signal_action           m_POLL_action;
0773     signal_action           m_ABRT_action;
0774     signal_action           m_ALRM_action;
0775 
0776     sigjmp_buf              m_sigjmp_buf;
0777     system_signal_exception m_sys_sig;
0778 
0779     static signal_handler*  s_active_handler;
0780 };
0781 
0782 // !! need to be placed in thread specific storage
0783 typedef signal_handler* signal_handler_ptr;
0784 signal_handler* signal_handler::s_active_handler = signal_handler_ptr();
0785 
0786 //____________________________________________________________________________//
0787 
0788 signal_handler::signal_handler( bool catch_system_errors,
0789                                 bool detect_fpe,
0790                                 unsigned long int timeout_microseconds,
0791                                 bool attach_dbg,
0792                                 char* alt_stack )
0793 : m_prev_handler( s_active_handler )
0794 , m_timeout_microseconds( timeout_microseconds )
0795 , m_ILL_action ( SIGILL , catch_system_errors,      attach_dbg, alt_stack )
0796 , m_FPE_action ( SIGFPE , detect_fpe         ,      attach_dbg, alt_stack )
0797 , m_SEGV_action( SIGSEGV, catch_system_errors,      attach_dbg, alt_stack )
0798 , m_BUS_action ( SIGBUS , catch_system_errors,      attach_dbg, alt_stack )
0799 #ifdef BOOST_TEST_CATCH_SIGPOLL
0800 , m_POLL_action( SIGPOLL, catch_system_errors,      attach_dbg, alt_stack )
0801 #endif
0802 , m_ABRT_action( SIGABRT, catch_system_errors,      attach_dbg, alt_stack )
0803 , m_ALRM_action( SIGALRM, timeout_microseconds > 0, attach_dbg, alt_stack )
0804 {
0805     s_active_handler = this;
0806 
0807     if( m_timeout_microseconds > 0 ) {
0808         ::alarm( 0 );
0809         ::alarm( static_cast<unsigned int>(std::ceil(timeout_microseconds / 1E6) )); // alarm has a precision to the seconds
0810     }
0811 
0812 #ifdef BOOST_TEST_USE_ALT_STACK
0813     if( alt_stack ) {
0814         stack_t sigstk;
0815         std::memset( &sigstk, 0, sizeof(stack_t) );
0816 
0817         BOOST_TEST_SYS_ASSERT( ::sigaltstack( 0, &sigstk ) != -1 );
0818 
0819         if( sigstk.ss_flags & SS_DISABLE ) {
0820             sigstk.ss_sp    = alt_stack;
0821             sigstk.ss_size  = BOOST_TEST_ALT_STACK_SIZE;
0822             sigstk.ss_flags = 0;
0823             BOOST_TEST_SYS_ASSERT( ::sigaltstack( &sigstk, 0 ) != -1 );
0824         }
0825     }
0826 #endif
0827 }
0828 
0829 //____________________________________________________________________________//
0830 
0831 signal_handler::~signal_handler()
0832 {
0833     assert( s_active_handler == this );
0834 
0835     if( m_timeout_microseconds > 0 )
0836         ::alarm( 0 );
0837 
0838 #ifdef BOOST_TEST_USE_ALT_STACK
0839 #ifdef __GNUC__
0840     // We shouldn't need to explicitly initialize all the members here,
0841     // but gcc warns if we don't, so add initializers for each of the
0842     // members specified in the POSIX std:
0843     stack_t sigstk = { 0, 0, 0 };
0844 #else
0845     stack_t sigstk = { };
0846 #endif
0847 
0848     sigstk.ss_size  = MINSIGSTKSZ;
0849     sigstk.ss_flags = SS_DISABLE;
0850     if( ::sigaltstack( &sigstk, 0 ) == -1 ) {
0851         int error_n = errno;
0852         std::cerr << "******** errors disabling the alternate stack:" << std::endl
0853                   << "\t#error:" << error_n << std::endl
0854                   << "\t" << std::strerror( error_n ) << std::endl;
0855     }
0856 #endif
0857 
0858     s_active_handler = m_prev_handler;
0859 }
0860 
0861 //____________________________________________________________________________//
0862 
0863 // ************************************************************************** //
0864 // **************       execution_monitor_signal_handler       ************** //
0865 // ************************************************************************** //
0866 
0867 extern "C" {
0868 
0869 static void boost_execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context )
0870 {
0871     signal_handler::sys_sig()( info, context );
0872 
0873     siglongjmp( signal_handler::jump_buffer(), sig );
0874 }
0875 
0876 //____________________________________________________________________________//
0877 
0878 static void boost_execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context )
0879 {
0880     if( !debug::attach_debugger( false ) )
0881         boost_execution_monitor_jumping_signal_handler( sig, info, context );
0882 
0883     // debugger attached; it will handle the signal
0884     BOOST_TEST_SYS_ASSERT( ::signal( sig, SIG_DFL ) != SIG_ERR );
0885 }
0886 
0887 //____________________________________________________________________________//
0888 
0889 }
0890 
0891 } // namespace detail
0892 
0893 // ************************************************************************** //
0894 // **************        execution_monitor::catch_signals      ************** //
0895 // ************************************************************************** //
0896 
0897 int
0898 execution_monitor::catch_signals( boost::function<int ()> const& F )
0899 {
0900     using namespace detail;
0901 
0902 #if defined(__CYGWIN__)
0903     p_catch_system_errors.value = false;
0904 #endif
0905 
0906 #ifdef BOOST_TEST_USE_ALT_STACK
0907     if( !!p_use_alt_stack && !m_alt_stack )
0908         m_alt_stack.reset( new char[BOOST_TEST_ALT_STACK_SIZE] );
0909 #else
0910     p_use_alt_stack.value = false;
0911 #endif
0912 
0913     signal_handler local_signal_handler( p_catch_system_errors,
0914                                          p_catch_system_errors || (p_detect_fp_exceptions != fpe::BOOST_FPE_OFF),
0915                                          p_timeout,
0916                                          p_auto_start_dbg,
0917                                          !p_use_alt_stack ? 0 : m_alt_stack.get() );
0918 
0919     if( !sigsetjmp( signal_handler::jump_buffer(), 1 ) )
0920         return detail::do_invoke( m_custom_translators , F );
0921     else
0922         BOOST_TEST_I_THROW( local_signal_handler.sys_sig() );
0923 }
0924 
0925 //____________________________________________________________________________//
0926 
0927 #elif defined(BOOST_SEH_BASED_SIGNAL_HANDLING)
0928 
0929 // ************************************************************************** //
0930 // **************   Microsoft structured exception handling    ************** //
0931 // ************************************************************************** //
0932 
0933 #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0564))
0934 namespace { void _set_se_translator( void* ) {} }
0935 #endif
0936 
0937 namespace detail {
0938 
0939 // ************************************************************************** //
0940 // **************    boost::detail::system_signal_exception    ************** //
0941 // ************************************************************************** //
0942 
0943 class system_signal_exception {
0944 public:
0945     // Constructor
0946     explicit            system_signal_exception( execution_monitor* em )
0947     : m_em( em )
0948     , m_se_id( 0 )
0949     , m_fault_address( 0 )
0950     , m_dir( false )
0951     , m_timeout( false )
0952     {}
0953 
0954     void                set_timed_out();
0955     void                report() const;
0956     int                 operator()( unsigned id, _EXCEPTION_POINTERS* exps );
0957 
0958 private:
0959     // Data members
0960     execution_monitor*  m_em;
0961 
0962     unsigned            m_se_id;
0963     void*               m_fault_address;
0964     bool                m_dir;
0965     bool                m_timeout;
0966 };
0967 
0968 //____________________________________________________________________________//
0969 
0970 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
0971 static void
0972 seh_catch_preventer( unsigned /* id */, _EXCEPTION_POINTERS* /* exps */ )
0973 {
0974     throw;
0975 }
0976 #endif
0977 
0978 //____________________________________________________________________________//
0979 
0980 void
0981 system_signal_exception::set_timed_out()
0982 {
0983     m_timeout = true;
0984 }
0985 
0986 //____________________________________________________________________________//
0987 
0988 int
0989 system_signal_exception::operator()( unsigned id, _EXCEPTION_POINTERS* exps )
0990 {
0991     const unsigned MSFT_CPP_EXCEPT = 0xE06d7363; // EMSC
0992 
0993     // C++ exception - allow to go through
0994     if( id == MSFT_CPP_EXCEPT )
0995         return EXCEPTION_CONTINUE_SEARCH;
0996 
0997     // FPE detection is enabled, while system exception detection is not - check if this is actually FPE
0998     if( !m_em->p_catch_system_errors ) {
0999         if( !m_em->p_detect_fp_exceptions )
1000             return EXCEPTION_CONTINUE_SEARCH;
1001 
1002         switch( id ) {
1003         case EXCEPTION_FLT_DIVIDE_BY_ZERO:
1004         case EXCEPTION_FLT_STACK_CHECK:
1005         case EXCEPTION_FLT_DENORMAL_OPERAND:
1006         case EXCEPTION_FLT_INEXACT_RESULT:
1007         case EXCEPTION_FLT_OVERFLOW:
1008         case EXCEPTION_FLT_UNDERFLOW:
1009         case EXCEPTION_FLT_INVALID_OPERATION:
1010         case STATUS_FLOAT_MULTIPLE_FAULTS:
1011         case STATUS_FLOAT_MULTIPLE_TRAPS:
1012             break;
1013         default:
1014             return EXCEPTION_CONTINUE_SEARCH;
1015         }
1016     }
1017 
1018     if( !!m_em->p_auto_start_dbg && debug::attach_debugger( false ) ) {
1019         m_em->p_catch_system_errors.value = false;
1020 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
1021         _set_se_translator( &seh_catch_preventer );
1022 #endif
1023         return EXCEPTION_CONTINUE_EXECUTION;
1024     }
1025 
1026     m_se_id = id;
1027     if( m_se_id == EXCEPTION_ACCESS_VIOLATION && exps->ExceptionRecord->NumberParameters == 2 ) {
1028         m_fault_address = (void*)exps->ExceptionRecord->ExceptionInformation[1];
1029         m_dir           = exps->ExceptionRecord->ExceptionInformation[0] == 0;
1030     }
1031 
1032     return EXCEPTION_EXECUTE_HANDLER;
1033 }
1034 
1035 //____________________________________________________________________________//
1036 
1037 void
1038 system_signal_exception::report() const
1039 {
1040     switch( m_se_id ) {
1041     // cases classified as system_fatal_error
1042     case EXCEPTION_ACCESS_VIOLATION: {
1043         if( !m_fault_address )
1044             detail::report_error( execution_exception::system_fatal_error, "memory access violation" );
1045         else
1046             detail::report_error(
1047                 execution_exception::system_fatal_error,
1048                     "memory access violation occurred at address 0x%" BOOST_TEST_PRIxPTR ", while attempting to %s",
1049                     m_fault_address,
1050                     m_dir ? " read inaccessible data"
1051                           : " write to an inaccessible (or protected) address"
1052                     );
1053         break;
1054     }
1055 
1056     case EXCEPTION_ILLEGAL_INSTRUCTION:
1057         detail::report_error( execution_exception::system_fatal_error, "illegal instruction" );
1058         break;
1059 
1060     case EXCEPTION_PRIV_INSTRUCTION:
1061         detail::report_error( execution_exception::system_fatal_error, "tried to execute an instruction whose operation is not allowed in the current machine mode" );
1062         break;
1063 
1064     case EXCEPTION_IN_PAGE_ERROR:
1065         detail::report_error( execution_exception::system_fatal_error, "access to a memory page that is not present" );
1066         break;
1067 
1068     case EXCEPTION_STACK_OVERFLOW:
1069         detail::report_error( execution_exception::system_fatal_error, "stack overflow" );
1070         break;
1071 
1072     case EXCEPTION_NONCONTINUABLE_EXCEPTION:
1073         detail::report_error( execution_exception::system_fatal_error, "tried to continue execution after a non continuable exception occurred" );
1074         break;
1075 
1076     // cases classified as (non-fatal) system_trap
1077     case EXCEPTION_DATATYPE_MISALIGNMENT:
1078         detail::report_error( execution_exception::system_error, "data misalignment" );
1079         break;
1080 
1081     case EXCEPTION_INT_DIVIDE_BY_ZERO:
1082         detail::report_error( execution_exception::system_error, "integer divide by zero" );
1083         break;
1084 
1085     case EXCEPTION_INT_OVERFLOW:
1086         detail::report_error( execution_exception::system_error, "integer overflow" );
1087         break;
1088 
1089     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1090         detail::report_error( execution_exception::system_error, "array bounds exceeded" );
1091         break;
1092 
1093     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
1094         detail::report_error( execution_exception::system_error, "floating point divide by zero" );
1095         break;
1096 
1097     case EXCEPTION_FLT_STACK_CHECK:
1098         detail::report_error( execution_exception::system_error,
1099                               "stack overflowed or underflowed as the result of a floating-point operation" );
1100         break;
1101 
1102     case EXCEPTION_FLT_DENORMAL_OPERAND:
1103         detail::report_error( execution_exception::system_error,
1104                               "operand of floating point operation is denormal" );
1105         break;
1106 
1107     case EXCEPTION_FLT_INEXACT_RESULT:
1108         detail::report_error( execution_exception::system_error,
1109                               "result of a floating-point operation cannot be represented exactly" );
1110         break;
1111 
1112     case EXCEPTION_FLT_OVERFLOW:
1113         detail::report_error( execution_exception::system_error,
1114                               "exponent of a floating-point operation is greater than the magnitude allowed by the corresponding type" );
1115         break;
1116 
1117     case EXCEPTION_FLT_UNDERFLOW:
1118         detail::report_error( execution_exception::system_error,
1119                               "exponent of a floating-point operation is less than the magnitude allowed by the corresponding type" );
1120         break;
1121 
1122     case EXCEPTION_FLT_INVALID_OPERATION:
1123         detail::report_error( execution_exception::system_error, "floating point error" );
1124         break;
1125 
1126     case STATUS_FLOAT_MULTIPLE_FAULTS:
1127         detail::report_error( execution_exception::system_error, "multiple floating point errors" );
1128         break;
1129 
1130     case STATUS_FLOAT_MULTIPLE_TRAPS:
1131         detail::report_error( execution_exception::system_error, "multiple floating point errors" );
1132         break;
1133 
1134     case EXCEPTION_BREAKPOINT:
1135         detail::report_error( execution_exception::system_error, "breakpoint encountered" );
1136         break;
1137 
1138     default:
1139         if( m_timeout ) {
1140             detail::report_error(execution_exception::timeout_error, "timeout while executing function");
1141         }
1142         else {
1143             detail::report_error( execution_exception::system_error, "unrecognized exception. Id: 0x%" BOOST_TEST_PRIxPTR, m_se_id );
1144         }
1145         break;
1146     }
1147 }
1148 
1149 //____________________________________________________________________________//
1150 
1151 // ************************************************************************** //
1152 // **************          assert_reporting_function           ************** //
1153 // ************************************************************************** //
1154 
1155 int BOOST_TEST_CALL_DECL
1156 assert_reporting_function( int reportType, char* userMessage, int* )
1157 {
1158     // write this way instead of switch to avoid unreachable statements
1159     if( reportType == BOOST_TEST_CRT_ASSERT || reportType == BOOST_TEST_CRT_ERROR )
1160         detail::report_error( reportType == BOOST_TEST_CRT_ASSERT ? execution_exception::user_error : execution_exception::system_error, userMessage );
1161 
1162     return 0;
1163 } // assert_reporting_function
1164 
1165 //____________________________________________________________________________//
1166 
1167 void BOOST_TEST_CALL_DECL
1168 invalid_param_handler( wchar_t const* /* expr */,
1169                        wchar_t const* /* func */,
1170                        wchar_t const* /* file */,
1171                        unsigned       /* line */,
1172                        uintptr_t      /* reserved */)
1173 {
1174     detail::report_error( execution_exception::user_error,
1175                           "Invalid parameter detected by C runtime library" );
1176 }
1177 
1178 //____________________________________________________________________________//
1179 
1180 } // namespace detail
1181 
1182 // ************************************************************************** //
1183 // **************        execution_monitor::catch_signals      ************** //
1184 // ************************************************************************** //
1185 
1186 int
1187 execution_monitor::catch_signals( boost::function<int ()> const& F )
1188 {
1189     _invalid_parameter_handler old_iph = _invalid_parameter_handler();
1190     BOOST_TEST_CRT_HOOK_TYPE old_crt_hook = 0;
1191 
1192     if( p_catch_system_errors ) {
1193         old_crt_hook = BOOST_TEST_CRT_SET_HOOK( &detail::assert_reporting_function );
1194 
1195         old_iph = _set_invalid_parameter_handler(
1196             reinterpret_cast<_invalid_parameter_handler>( &detail::invalid_param_handler ) );
1197     } else if( !p_detect_fp_exceptions ) {
1198 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
1199         _set_se_translator( &detail::seh_catch_preventer );
1200 #endif
1201     }
1202 
1203 #if defined(BOOST_TEST_WIN32_WAITABLE_TIMERS)
1204     HANDLE htimer = INVALID_HANDLE_VALUE;
1205     BOOL bTimerSuccess = FALSE;
1206 
1207     if( p_timeout ) {
1208         htimer = ::CreateWaitableTimer(
1209             NULL,
1210             TRUE,
1211             NULL); // naming the timer might create collisions
1212 
1213         if( htimer != INVALID_HANDLE_VALUE ) {
1214             LARGE_INTEGER liDueTime;
1215             liDueTime.QuadPart = - static_cast<LONGLONG>(p_timeout) * 10ll; // resolution of 100 ns
1216 
1217             bTimerSuccess = ::SetWaitableTimer(
1218                 htimer,
1219                 &liDueTime,
1220                 0,
1221                 0,
1222                 0,
1223                 FALSE);           // Do not restore a suspended system
1224         }
1225     }
1226 #endif 
1227 
1228     detail::system_signal_exception SSE( this );
1229 
1230     int ret_val = 0;
1231     // clang windows workaround: this not available in __finally scope
1232     bool l_catch_system_errors = p_catch_system_errors;
1233 
1234     __try {
1235         __try {
1236             ret_val = detail::do_invoke( m_custom_translators, F );
1237         }
1238         __except( SSE( GetExceptionCode(), GetExceptionInformation() ) ) {
1239             throw SSE;
1240         }
1241 
1242         // we check for time outs: we do not have any signaling facility on Win32
1243         // however, we signal a timeout as a hard error as for the other operating systems
1244         // and throw the signal error handler
1245         if( bTimerSuccess && htimer != INVALID_HANDLE_VALUE) {
1246             if (::WaitForSingleObject(htimer, 0) == WAIT_OBJECT_0) {
1247                 SSE.set_timed_out();
1248                 throw SSE;
1249             }
1250         }
1251 
1252     }
1253     __finally {
1254 
1255 #if defined(BOOST_TEST_WIN32_WAITABLE_TIMERS)
1256         if( htimer != INVALID_HANDLE_VALUE ) {
1257             ::CloseHandle(htimer);
1258         }
1259 #endif
1260 
1261         if( l_catch_system_errors ) {
1262             BOOST_TEST_CRT_SET_HOOK( old_crt_hook );
1263 
1264            _set_invalid_parameter_handler( old_iph );
1265         }
1266     }
1267 
1268     return ret_val;
1269 }
1270 
1271 //____________________________________________________________________________//
1272 
1273 #else  // default signal handler
1274 
1275 namespace detail {
1276 
1277 class system_signal_exception {
1278 public:
1279     void   report() const {}
1280 };
1281 
1282 } // namespace detail
1283 
1284 int
1285 execution_monitor::catch_signals( boost::function<int ()> const& F )
1286 {
1287     return detail::do_invoke( m_custom_translators , F );
1288 }
1289 
1290 //____________________________________________________________________________//
1291 
1292 #endif  // choose signal handler
1293 
1294 // ************************************************************************** //
1295 // **************              execution_monitor               ************** //
1296 // ************************************************************************** //
1297 
1298 execution_monitor::execution_monitor()
1299 : p_catch_system_errors( true )
1300 , p_auto_start_dbg( false )
1301 , p_timeout( 0 )
1302 , p_use_alt_stack( true )
1303 , p_detect_fp_exceptions( fpe::BOOST_FPE_OFF )
1304 {}
1305 
1306 //____________________________________________________________________________//
1307 
1308 int
1309 execution_monitor::execute( boost::function<int ()> const& F )
1310 {
1311     if( debug::under_debugger() )
1312         p_catch_system_errors.value = false;
1313 
1314     BOOST_TEST_I_TRY {
1315         detail::fpe_except_guard G( p_detect_fp_exceptions );
1316         boost::ignore_unused( G );
1317 
1318         return catch_signals( F );
1319     }
1320 
1321 #ifndef BOOST_NO_EXCEPTIONS
1322 
1323     //  Catch-clause reference arguments are a bit different from function
1324     //  arguments (ISO 15.3 paragraphs 18 & 19).  Apparently const isn't
1325     //  required.  Programmers ask for const anyhow, so we supply it.  That's
1326     //  easier than answering questions about non-const usage.
1327 
1328     catch( char const* ex )
1329       { detail::report_error( execution_exception::cpp_exception_error,
1330                               "C string: %s", ex ); }
1331     catch( std::string const& ex )
1332       { detail::report_error( execution_exception::cpp_exception_error,
1333                               "std::string: %s", ex.c_str() ); }
1334 
1335     // boost::exception (before std::exception, with extended diagnostic)
1336     catch( boost::exception const& ex )
1337       { detail::report_error( execution_exception::cpp_exception_error,
1338                               &ex,
1339                               "%s", boost::diagnostic_information(ex).c_str() ); }
1340 
1341     //  std:: exceptions
1342 #if defined(BOOST_NO_TYPEID) || defined(BOOST_NO_RTTI)
1343 #define CATCH_AND_REPORT_STD_EXCEPTION( ex_name )                           \
1344     catch( ex_name const& ex )                                              \
1345        { detail::report_error( execution_exception::cpp_exception_error,    \
1346                           current_exception_cast<boost::exception const>(), \
1347                           #ex_name ": %s", ex.what() ); }                   \
1348 /**/
1349 #else
1350 #define CATCH_AND_REPORT_STD_EXCEPTION( ex_name )                           \
1351     catch( ex_name const& ex )                                              \
1352         { detail::report_error( execution_exception::cpp_exception_error,   \
1353                           current_exception_cast<boost::exception const>(), \
1354                           "%s: %s", detail::typeid_name(ex).c_str(), ex.what() ); } \
1355 /**/
1356 #endif
1357 
1358     CATCH_AND_REPORT_STD_EXCEPTION( std::bad_alloc )
1359     CATCH_AND_REPORT_STD_EXCEPTION( std::bad_cast )
1360     CATCH_AND_REPORT_STD_EXCEPTION( std::bad_typeid )
1361     CATCH_AND_REPORT_STD_EXCEPTION( std::bad_exception )
1362     CATCH_AND_REPORT_STD_EXCEPTION( std::domain_error )
1363     CATCH_AND_REPORT_STD_EXCEPTION( std::invalid_argument )
1364     CATCH_AND_REPORT_STD_EXCEPTION( std::length_error )
1365     CATCH_AND_REPORT_STD_EXCEPTION( std::out_of_range )
1366     CATCH_AND_REPORT_STD_EXCEPTION( std::range_error )
1367     CATCH_AND_REPORT_STD_EXCEPTION( std::overflow_error )
1368     CATCH_AND_REPORT_STD_EXCEPTION( std::underflow_error )
1369     CATCH_AND_REPORT_STD_EXCEPTION( std::logic_error )
1370     CATCH_AND_REPORT_STD_EXCEPTION( std::runtime_error )
1371     CATCH_AND_REPORT_STD_EXCEPTION( std::exception )
1372 #undef CATCH_AND_REPORT_STD_EXCEPTION
1373 
1374     // system errors
1375     catch( system_error const& ex )
1376       { detail::report_error( execution_exception::cpp_exception_error,
1377                               "system_error produced by: %s: %s", ex.p_failed_exp, std::strerror( ex.p_errno ) ); }
1378     catch( detail::system_signal_exception const& ex )
1379       { ex.report(); }
1380 
1381     // not an error
1382     catch( execution_aborted const& )
1383       { return 0; }
1384 
1385     // just forward
1386     catch( execution_exception const& )
1387       { throw; }
1388 
1389     // unknown error
1390     catch( ... )
1391       { detail::report_error( execution_exception::cpp_exception_error, "unknown type" ); }
1392 
1393 #endif // !BOOST_NO_EXCEPTIONS
1394 
1395     BOOST_TEST_UNREACHABLE_RETURN(0);  // never reached; supplied to quiet compiler warnings
1396 } // execute
1397 
1398 //____________________________________________________________________________//
1399 
1400 namespace detail {
1401 
1402 struct forward {
1403     explicit    forward( boost::function<void ()> const& F ) : m_F( F ) {}
1404 
1405     int         operator()() { m_F(); return 0; }
1406 
1407     boost::function<void ()> const& m_F;
1408 };
1409 
1410 } // namespace detail
1411 void
1412 execution_monitor::vexecute( boost::function<void ()> const& F )
1413 {
1414     execute( detail::forward( F ) );
1415 }
1416 
1417 // ************************************************************************** //
1418 // **************                  system_error                ************** //
1419 // ************************************************************************** //
1420 
1421 system_error::system_error( char const* exp )
1422 #ifdef UNDER_CE
1423 : p_errno( GetLastError() )
1424 #else
1425 : p_errno( errno )
1426 #endif
1427 , p_failed_exp( exp )
1428 {}
1429 
1430 //____________________________________________________________________________//
1431 
1432 // ************************************************************************** //
1433 // **************              execution_exception             ************** //
1434 // ************************************************************************** //
1435 
1436 execution_exception::execution_exception( error_code ec_, const_string what_msg_, location const& location_ )
1437 : m_error_code( ec_ )
1438 , m_what( what_msg_.empty() ? BOOST_TEST_L( "uncaught exception, system error or abort requested" ) : what_msg_ )
1439 , m_location( location_ )
1440 {}
1441 
1442 //____________________________________________________________________________//
1443 
1444 execution_exception::location::location( char const* file_name, size_t line_num, char const* func )
1445 : m_file_name( file_name ? file_name : "unknown location" )
1446 , m_line_num( line_num )
1447 , m_function( func )
1448 {}
1449 
1450 execution_exception::location::location(const_string file_name, size_t line_num, char const* func )
1451 : m_file_name( file_name )
1452 , m_line_num( line_num )
1453 , m_function( func )
1454 {}
1455 
1456 //____________________________________________________________________________//
1457 
1458 // ************************************************************************** //
1459 // **************Floating point exception management interface ************** //
1460 // ************************************************************************** //
1461 
1462 namespace fpe {
1463 
1464 unsigned
1465 enable( unsigned mask )
1466 {
1467     boost::ignore_unused(mask);
1468 #if defined(BOOST_TEST_FPE_SUPPORT_WITH_SEH__)
1469     _clearfp();
1470 
1471 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
1472     unsigned old_cw = ::_controlfp( 0, 0 );
1473     ::_controlfp( old_cw & ~mask, BOOST_FPE_ALL );
1474 #else
1475     unsigned old_cw;
1476     if( ::_controlfp_s( &old_cw, 0, 0 ) != 0 )
1477         return BOOST_FPE_INV;
1478 
1479     // Set the control word
1480     if( ::_controlfp_s( 0, old_cw & ~mask, BOOST_FPE_ALL ) != 0 )
1481         return BOOST_FPE_INV;
1482 #endif
1483     return ~old_cw & BOOST_FPE_ALL;
1484 
1485 #elif defined(BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__)
1486     // same macro definition as in execution_monitor.hpp
1487     if (BOOST_FPE_ALL == BOOST_FPE_OFF)
1488         /* Not Implemented */
1489         return BOOST_FPE_OFF;
1490     feclearexcept(BOOST_FPE_ALL);
1491     int res = feenableexcept( mask );
1492     return res == -1 ? (unsigned)BOOST_FPE_INV : (unsigned)res;
1493 #else
1494     /* Not Implemented  */
1495     return BOOST_FPE_OFF;
1496 #endif
1497 }
1498 
1499 //____________________________________________________________________________//
1500 
1501 unsigned
1502 disable( unsigned mask )
1503 {
1504     boost::ignore_unused(mask);
1505 
1506 #if defined(BOOST_TEST_FPE_SUPPORT_WITH_SEH__)
1507     _clearfp();
1508 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
1509     unsigned old_cw = ::_controlfp( 0, 0 );
1510     ::_controlfp( old_cw | mask, BOOST_FPE_ALL );
1511 #else
1512     unsigned old_cw;
1513     if( ::_controlfp_s( &old_cw, 0, 0 ) != 0 )
1514         return BOOST_FPE_INV;
1515 
1516     // Set the control word
1517     if( ::_controlfp_s( 0, old_cw | mask, BOOST_FPE_ALL ) != 0 )
1518         return BOOST_FPE_INV;
1519 #endif
1520     return ~old_cw & BOOST_FPE_ALL;
1521 
1522 #elif defined(BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__)
1523     if (BOOST_FPE_ALL == BOOST_FPE_OFF)
1524         /* Not Implemented */
1525         return BOOST_FPE_INV;
1526     feclearexcept(BOOST_FPE_ALL);
1527     int res = fedisableexcept( mask );
1528     return res == -1 ? (unsigned)BOOST_FPE_INV : (unsigned)res;
1529 #else
1530     /* Not Implemented */
1531     return BOOST_FPE_INV;
1532 #endif
1533 }
1534 
1535 //____________________________________________________________________________//
1536 
1537 } // namespace fpe
1538 
1539 } // namespace boost
1540 
1541 #include <boost/test/detail/enable_warnings.hpp>
1542 
1543 #endif // BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER