Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:06:38

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