LCOV - code coverage report
Current view: top level - opt/homebrew/include/boost/test/impl - execution_monitor.ipp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 110 320 34.4 %
Date: 2026-06-25 07:23:51 Functions: 27 61 44.3 %

          Line data    Source code
       1             : //  (C) Copyright Gennadiy Rozental 2001.
       2             : //  (C) Copyright Beman Dawes and Ullrich Koethe 1995-2001.
       3             : //  Use, modification, and distribution are subject to the
       4             : //  Boost Software License, Version 1.0. (See accompanying file
       5             : //  http://www.boost.org/LICENSE_1_0.txt)
       6             : 
       7             : //  See http://www.boost.org/libs/test for the library home page.
       8             : //
       9             : ///  @file
      10             : ///  Provides execution monitor implementation for all supported
      11             : ///  configurations, including Microsoft structured exception based, unix signals
      12             : ///  based and special workarounds for borland
      13             : ///
      14             : ///  Note that when testing requirements or user wishes preclude use of this
      15             : ///  file as a separate compilation unit, it may be included as a header file.
      16             : ///
      17             : ///  Header dependencies are deliberately restricted to reduce coupling to other
      18             : ///  boost libraries.
      19             : // ***************************************************************************
      20             : 
      21             : #ifndef BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER
      22             : #define BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER
      23             : 
      24             : // Boost.Test
      25             : #include <boost/test/detail/config.hpp>
      26             : #include <boost/test/detail/throw_exception.hpp>
      27             : #include <boost/test/execution_monitor.hpp>
      28             : #include <boost/test/debug.hpp>
      29             : 
      30             : // Boost
      31             : #include <boost/cstdlib.hpp>    // for exit codes
      32             : #include <boost/config.hpp>     // for workarounds
      33             : #include <boost/core/ignore_unused.hpp> // for ignore_unused
      34             : #ifndef BOOST_NO_EXCEPTIONS
      35             : #include <boost/exception/get_error_info.hpp> // for get_error_info
      36             : #include <boost/exception/current_exception_cast.hpp> // for current_exception_cast
      37             : #include <boost/exception/diagnostic_information.hpp>
      38             : #endif
      39             : 
      40             : // STL
      41             : #include <string>               // for std::string
      42             : #include <new>                  // for std::bad_alloc
      43             : #include <typeinfo>             // for std::bad_cast, std::bad_typeid
      44             : #include <exception>            // for std::exception, std::bad_exception
      45             : #include <stdexcept>            // for std exception hierarchy
      46             : #include <cstring>              // for C string API
      47             : #include <cassert>              // for assert
      48             : #include <cstddef>              // for NULL
      49             : #include <cstdio>               // for vsnprintf
      50             : #include <stdio.h>
      51             : #include <cstdarg>              // for varargs
      52             : #include <stdarg.h>
      53             : #include <cmath>                // for ceil
      54             : 
      55             : #include <iostream>              // for varargs
      56             : 
      57             : #ifdef BOOST_NO_STDC_NAMESPACE
      58             : namespace std { using ::strerror; using ::strlen; using ::strncat; using ::ceil; }
      59             : #endif
      60             : 
      61             : // to use vsnprintf
      62             : #if defined(__SUNPRO_CC) || defined(__SunOS) || defined(__QNXNTO__) || defined(__VXWORKS__)
      63             : using std::va_list;
      64             : #endif
      65             : 
      66             : #if defined(__VXWORKS__)
      67             : # define BOOST_TEST_LIMITED_SIGNAL_DETAILS
      68             : #endif
      69             : 
      70             : #ifdef BOOST_SEH_BASED_SIGNAL_HANDLING
      71             : 
      72             : # if !defined(_WIN32_WINNT) // WinXP
      73             : #   define _WIN32_WINNT  0x0501
      74             : # endif
      75             : 
      76             : #  include <windows.h>
      77             : 
      78             : #  if defined(__MWERKS__) || (defined(_MSC_VER) && !defined(UNDER_CE))
      79             : #    include <eh.h>
      80             : #  endif
      81             : 
      82             : #  if defined(BOOST_BORLANDC) && BOOST_BORLANDC >= 0x560 || defined(__MWERKS__)
      83             : #    include <stdint.h>
      84             : #  endif
      85             : 
      86             : #  if defined(BOOST_BORLANDC) && BOOST_BORLANDC < 0x560
      87             :     typedef unsigned uintptr_t;
      88             : #  endif
      89             : 
      90             : #  if defined(UNDER_CE) && BOOST_WORKAROUND(_MSC_VER,  < 1500 )
      91             :    typedef void* uintptr_t;
      92             : #  elif defined(UNDER_CE)
      93             : #  include <crtdefs.h>
      94             : #  endif
      95             : 
      96             : #  if !defined(NDEBUG) && defined(_MSC_VER) && !defined(UNDER_CE)
      97             : #    include <crtdbg.h>
      98             : #    define BOOST_TEST_CRT_HOOK_TYPE    _CRT_REPORT_HOOK
      99             : #    define BOOST_TEST_CRT_ASSERT       _CRT_ASSERT
     100             : #    define BOOST_TEST_CRT_ERROR        _CRT_ERROR
     101             : #    define BOOST_TEST_CRT_SET_HOOK(H)  _CrtSetReportHook(H)
     102             : #  else
     103             : #    define BOOST_TEST_CRT_HOOK_TYPE    void*
     104             : #    define BOOST_TEST_CRT_ASSERT       2
     105             : #    define BOOST_TEST_CRT_ERROR        1
     106             : #    define BOOST_TEST_CRT_SET_HOOK(H)  (void*)(H)
     107             : #  endif
     108             : 
     109             : #  if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) /* WinXP */
     110             : #    define BOOST_TEST_WIN32_WAITABLE_TIMERS
     111             : #  endif
     112             : 
     113             : #  if (!BOOST_WORKAROUND(_MSC_VER,  >= 1400 ) && \
     114             :       !defined(BOOST_COMO)) || defined(UNDER_CE)
     115             : 
     116             : typedef void* _invalid_parameter_handler;
     117             : 
     118             : inline _invalid_parameter_handler
     119             : _set_invalid_parameter_handler( _invalid_parameter_handler arg )
     120             : {
     121             :     return arg;
     122             : }
     123             : 
     124             : #  endif
     125             : 
     126             : #  if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0564)) || defined(UNDER_CE)
     127             : 
     128             : namespace { void _set_se_translator( void* ) {} }
     129             : 
     130             : #  endif
     131             : 
     132             : #elif defined(BOOST_HAS_SIGACTION)
     133             : 
     134             : #  define BOOST_SIGACTION_BASED_SIGNAL_HANDLING
     135             : 
     136             : #  include <unistd.h>
     137             : #  include <signal.h>
     138             : #  include <setjmp.h>
     139             : 
     140             : #  if defined(__FreeBSD__)
     141             : 
     142             : #    include <osreldate.h>
     143             : 
     144             : #    ifndef SIGPOLL
     145             : #      define SIGPOLL SIGIO
     146             : #    endif
     147             : 
     148             : #    if (__FreeBSD_version < 70100)
     149             : 
     150             : #      define ILL_ILLADR 0 // ILL_RESAD_FAULT
     151             : #      define ILL_PRVOPC ILL_PRIVIN_FAULT
     152             : #      define ILL_ILLOPN 2 // ILL_RESOP_FAULT
     153             : #      define ILL_COPROC ILL_FPOP_FAULT
     154             : 
     155             : #      define BOOST_TEST_LIMITED_SIGNAL_DETAILS
     156             : 
     157             : #    endif
     158             : #  endif
     159             : 
     160             : #  if defined(__ANDROID__)
     161             : #    include <android/api-level.h>
     162             : #  endif
     163             : 
     164             : // documentation of BOOST_TEST_DISABLE_ALT_STACK in execution_monitor.hpp
     165             : #  if !defined(__CYGWIN__) && !defined(__QNXNTO__) && !defined(__bgq__) && \
     166             :    (!defined(__ANDROID__) || __ANDROID_API__ >= 8) && !defined(__wasm__) && \
     167             :    !defined(BOOST_TEST_DISABLE_ALT_STACK)
     168             : #    define BOOST_TEST_USE_ALT_STACK
     169             : #  endif
     170             : 
     171             : #  if defined(SIGPOLL) && !defined(__CYGWIN__)                              && \
     172             :       !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))  && \
     173             :       !defined(__NetBSD__)                                                  && \
     174             :       !defined(__QNXNTO__)
     175             : #    define BOOST_TEST_CATCH_SIGPOLL
     176             : #  endif
     177             : 
     178             : #  ifdef BOOST_TEST_USE_ALT_STACK
     179             : #    define BOOST_TEST_ALT_STACK_SIZE SIGSTKSZ
     180             : #  endif
     181             : 
     182             : 
     183             : #else
     184             : 
     185             : #  define BOOST_NO_SIGNAL_HANDLING
     186             : 
     187             : #endif
     188             : 
     189             : #ifndef UNDER_CE
     190             : #include <errno.h>
     191             : #endif
     192             : 
     193             : #if !defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
     194             : #  include <boost/core/demangle.hpp>
     195             : #endif
     196             : 
     197             : #if (!defined(BOOST_MSSTL_VERSION) || (BOOST_MSSTL_VERSION >= 120)) && (!defined(__GLIBC__) || ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 2))))
     198             : // glibc 2.2 - 2.17 required __STDC_FORMAT_MACROS to be defined for use of PRIxPTR, as well as some versions of macOS.
     199             : #  if (defined(__GLIBC__) && !((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 18)))) || defined(__APPLE__)
     200             : #    ifndef __STDC_FORMAT_MACROS
     201             : #      define __STDC_FORMAT_MACROS 1
     202             : #      define BOOST_TEST_DEFINED_STDC_FORMAT_MACROS
     203             : #    endif
     204             : #  endif
     205             : #  include <inttypes.h>
     206             : #  define BOOST_TEST_PRIxPTR PRIxPTR
     207             : #  ifdef BOOST_TEST_DEFINED_STDC_FORMAT_MACROS
     208             : #    undef __STDC_FORMAT_MACROS
     209             : #  endif
     210             : #endif
     211             : // If any modern toolchain did not pick up a definition from above it will here
     212             : #ifndef BOOST_TEST_PRIxPTR
     213             : #  ifdef __has_include
     214             : #    if __has_include(<cinttypes>)
     215             : #      include <cinttypes>
     216             : #      define BOOST_TEST_PRIxPTR PRIxPTR
     217             : #    endif
     218             : #  endif
     219             : #endif
     220             : // Last resort
     221             : #ifndef BOOST_TEST_PRIxPTR
     222             : #  define BOOST_TEST_PRIxPTR "08lx"
     223             : #endif
     224             : 
     225             : #include <boost/test/detail/suppress_warnings.hpp>
     226             : 
     227             : //____________________________________________________________________________//
     228             : 
     229             : namespace boost {
     230             : 
     231             : // ************************************************************************** //
     232             : // **************                 throw_exception              ************** //
     233             : // ************************************************************************** //
     234             : 
     235             : #ifdef BOOST_NO_EXCEPTIONS
     236             : void throw_exception( std::exception const & e ) { abort(); }
     237             : #endif
     238             : 
     239             : // ************************************************************************** //
     240             : // **************                  report_error                ************** //
     241             : // ************************************************************************** //
     242             : 
     243             : namespace detail {
     244             : 
     245             : #ifdef BOOST_BORLANDC
     246             : #  define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) std::vsnprintf( (a1), (a2), (a3), (a4) )
     247             : #elif BOOST_WORKAROUND(_MSC_VER, <= 1310) || \
     248             :       BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3000)) || \
     249             :       defined(UNDER_CE) || \
     250             :       (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
     251             : #  define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) _vsnprintf( (a1), (a2), (a3), (a4) )
     252             : #else
     253             : #  define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) vsnprintf( (a1), (a2), (a3), (a4) )
     254             : #endif
     255             : 
     256             : 
     257             : /* checks the printf formatting by adding a decorator to the function */
     258             : #if __GNUC__ >= 3 || defined(BOOST_EMBTC)
     259             : #define BOOST_TEST_PRINTF_ATTRIBUTE_CHECK(x, y) __attribute__((__format__ (__printf__, x, y)))
     260             : #else
     261             : #define BOOST_TEST_PRINTF_ATTRIBUTE_CHECK(x, y)
     262             : #endif
     263             : 
     264             : #ifndef BOOST_NO_EXCEPTIONS
     265             : 
     266             : template <typename ErrorInfo>
     267             : typename ErrorInfo::value_type
     268           0 : extract( boost::exception const* ex )
     269             : {
     270           0 :     if( !ex )
     271           0 :         return 0;
     272             : 
     273           0 :     typename ErrorInfo::value_type const * val = boost::get_error_info<ErrorInfo>( *ex );
     274             : 
     275           0 :     return val ? *val : 0;
     276           0 : }
     277             : 
     278             : //____________________________________________________________________________//
     279             : 
     280             : static void
     281             : BOOST_TEST_PRINTF_ATTRIBUTE_CHECK(3, 0)
     282           0 : report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, va_list* args )
     283             : {
     284             :     static const int REPORT_ERROR_BUFFER_SIZE = 4096;
     285             :     static char buf[REPORT_ERROR_BUFFER_SIZE];
     286             : 
     287           0 :     BOOST_TEST_VSNPRINTF( buf, sizeof(buf)-1, format, *args );
     288           0 :     buf[sizeof(buf)-1] = 0;
     289             : 
     290           0 :     va_end( *args );
     291             : 
     292           0 :     BOOST_TEST_I_THROW(execution_exception( ec, buf, execution_exception::location( extract<throw_file>( be ),
     293             :                                                                                     (size_t)extract<throw_line>( be ),
     294             :                                                                                     extract<throw_function>( be ) ) ));
     295             : }
     296             : 
     297             : //____________________________________________________________________________//
     298             : 
     299             : static void
     300             : BOOST_TEST_PRINTF_ATTRIBUTE_CHECK(3, 4)
     301           0 : report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, ... )
     302             : {
     303             :     va_list args;
     304           0 :     va_start( args, format );
     305             : 
     306           0 :     report_error( ec, be, format, &args );
     307           0 : }
     308             : 
     309             : #endif
     310             : 
     311             : //____________________________________________________________________________//
     312             : 
     313             : static void
     314             : BOOST_TEST_PRINTF_ATTRIBUTE_CHECK(2, 3)
     315           0 : report_error( execution_exception::error_code ec, char const* format, ... )
     316             : {
     317             :     va_list args;
     318           0 :     va_start( args, format );
     319             : 
     320           0 :     report_error( ec, 0, format, &args );
     321           0 : }
     322             : 
     323             : //____________________________________________________________________________//
     324             : 
     325             : template<typename Tr,typename Functor>
     326             : inline int
     327        1315 : do_invoke( Tr const& tr, Functor const& F )
     328             : {
     329        1315 :     return tr ? (*tr)( F ) : F();
     330             : }
     331             : 
     332             : //____________________________________________________________________________//
     333             : 
     334             : struct fpe_except_guard {
     335        2630 :     explicit fpe_except_guard( unsigned detect_fpe )
     336        1315 :     : m_detect_fpe( detect_fpe )
     337        1315 :     {
     338             :         // prepare fp exceptions control
     339        1315 :         m_previously_enabled = fpe::disable( fpe::BOOST_FPE_ALL );
     340        1315 :         if( m_previously_enabled != fpe::BOOST_FPE_INV && detect_fpe != fpe::BOOST_FPE_OFF )
     341           0 :             fpe::enable( detect_fpe );
     342        2630 :     }
     343        2628 :     ~fpe_except_guard()
     344        1314 :     {
     345        1314 :         if( m_detect_fpe != fpe::BOOST_FPE_OFF )
     346           0 :             fpe::disable( m_detect_fpe );
     347        1314 :         if( m_previously_enabled != fpe::BOOST_FPE_INV )
     348           0 :             fpe::enable( m_previously_enabled );
     349        2628 :     }
     350             : 
     351             :     unsigned m_detect_fpe;
     352             :     unsigned m_previously_enabled;
     353             : };
     354             : 
     355             : 
     356             : // ************************************************************************** //
     357             : // **************                  typeid_name                 ************** //
     358             : // ************************************************************************** //
     359             : 
     360             : #if !defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
     361             : template<typename T>
     362             : std::string
     363           0 : typeid_name( T const& t )
     364             : {
     365           0 :     return boost::core::demangle(typeid(t).name());
     366             : }
     367             : #endif
     368             : 
     369             : } // namespace detail
     370             : 
     371             : #if defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING)
     372             : 
     373             : // ************************************************************************** //
     374             : // **************       Sigaction based signal handling        ************** //
     375             : // ************************************************************************** //
     376             : 
     377             : namespace detail {
     378             : 
     379             : // ************************************************************************** //
     380             : // **************    boost::detail::system_signal_exception    ************** //
     381             : // ************************************************************************** //
     382             : 
     383             : class system_signal_exception {
     384             : public:
     385             :     // Constructor
     386        2630 :     system_signal_exception()
     387        1315 :     : m_sig_info( 0 )
     388        1315 :     , m_context( 0 )
     389        2630 :     {}
     390             : 
     391             :     // Access methods
     392           0 :     void        operator()( siginfo_t* i, void* c )
     393             :     {
     394           0 :         m_sig_info  = i;
     395           0 :         m_context   = c;
     396           0 :     }
     397             :     void        report() const;
     398             : 
     399             : private:
     400             :     // Data members
     401             :     siginfo_t*  m_sig_info; // system signal detailed info
     402             :     void*       m_context;  // signal context
     403             : };
     404             : 
     405             : //____________________________________________________________________________//
     406             : 
     407             : void
     408           0 : system_signal_exception::report() const
     409             : {
     410           0 :     if( !m_sig_info )
     411           0 :         return; // no error actually occur?
     412             : 
     413           0 :     switch( m_sig_info->si_code ) {
     414             : #ifdef __VXWORKS__
     415             : // a bit of a hack to adapt code to small m_sig_info VxWorks uses
     416             : #define si_addr si_value.sival_int
     417             : #define si_band si_value.sival_int
     418             : #else
     419             :     case SI_USER:
     420           0 :         report_error( execution_exception::system_error,
     421             :                       "signal: generated by kill() (or family); uid=%d; pid=%d",
     422           0 :                       (int)m_sig_info->si_uid, (int)m_sig_info->si_pid );
     423           0 :         break;
     424             : #endif
     425             :     case SI_QUEUE:
     426           0 :         report_error( execution_exception::system_error,
     427             :                       "signal: sent by sigqueue()" );
     428           0 :         break;
     429             :     case SI_TIMER:
     430           0 :         report_error( execution_exception::system_error,
     431             :                       "signal: the expiration of a timer set by timer_settimer()" );
     432           0 :         break;
     433             : // OpenBSD was missing SI_ASYNCIO and SI_MESGQ
     434             : #ifdef SI_ASYNCIO
     435             :     case SI_ASYNCIO:
     436           0 :         report_error( execution_exception::system_error,
     437             :                       "signal: generated by the completion of an asynchronous I/O request" );
     438           0 :         break;
     439             : #endif
     440             : #ifdef SI_MESGQ
     441             :     case SI_MESGQ:
     442           0 :         report_error( execution_exception::system_error,
     443             :                       "signal: generated by the the arrival of a message on an empty message queue" );
     444           0 :         break;
     445             : #endif
     446             :     default:
     447           0 :         break;
     448             :     }
     449             : 
     450           0 :     switch( m_sig_info->si_signo ) {
     451             :     case SIGILL:
     452           0 :         switch( m_sig_info->si_code ) {
     453             : #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
     454             :         case ILL_ILLOPC:
     455           0 :             report_error( execution_exception::system_fatal_error,
     456             :                           "signal: illegal opcode; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
     457           0 :                           (uintptr_t) m_sig_info->si_addr );
     458           0 :             break;
     459             :         case ILL_ILLTRP:
     460           0 :             report_error( execution_exception::system_fatal_error,
     461             :                           "signal: illegal trap; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
     462           0 :                           (uintptr_t) m_sig_info->si_addr );
     463           0 :             break;
     464             :         case ILL_PRVREG:
     465           0 :             report_error( execution_exception::system_fatal_error,
     466             :                           "signal: privileged register; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
     467           0 :                           (uintptr_t) m_sig_info->si_addr );
     468           0 :             break;
     469             :         case ILL_BADSTK:
     470           0 :             report_error( execution_exception::system_fatal_error,
     471             :                           "signal: internal stack error; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
     472           0 :                           (uintptr_t) m_sig_info->si_addr );
     473           0 :             break;
     474             : #endif
     475             :         case ILL_ILLOPN:
     476           0 :             report_error( execution_exception::system_fatal_error,
     477             :                           "signal: illegal operand; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
     478           0 :                           (uintptr_t) m_sig_info->si_addr );
     479           0 :             break;
     480             :         case ILL_ILLADR:
     481           0 :             report_error( execution_exception::system_fatal_error,
     482             :                           "signal: illegal addressing mode; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
     483           0 :                           (uintptr_t) m_sig_info->si_addr );
     484           0 :             break;
     485             :         case ILL_PRVOPC:
     486           0 :             report_error( execution_exception::system_fatal_error,
     487             :                           "signal: privileged opcode; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
     488           0 :                           (uintptr_t) m_sig_info->si_addr );
     489           0 :             break;
     490             :         case ILL_COPROC:
     491           0 :             report_error( execution_exception::system_fatal_error,
     492             :                           "signal: co-processor error; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
     493           0 :                           (uintptr_t) m_sig_info->si_addr );
     494           0 :             break;
     495             :         default:
     496           0 :             report_error( execution_exception::system_fatal_error,
     497             :                           "signal: SIGILL, si_code: %d (illegal instruction; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR ")",
     498           0 :                           m_sig_info->si_code, (uintptr_t) m_sig_info->si_addr );
     499           0 :             break;
     500             :         }
     501           0 :         break;
     502             : 
     503             :     case SIGFPE:
     504           0 :         switch( m_sig_info->si_code ) {
     505             :         case FPE_INTDIV:
     506           0 :             report_error( execution_exception::system_error,
     507             :                           "signal: integer divide by zero; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
     508           0 :                           (uintptr_t) m_sig_info->si_addr );
     509           0 :             break;
     510             :         case FPE_INTOVF:
     511           0 :             report_error( execution_exception::system_error,
     512             :                           "signal: integer overflow; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
     513           0 :                           (uintptr_t) m_sig_info->si_addr );
     514           0 :             break;
     515             :         case FPE_FLTDIV:
     516           0 :             report_error( execution_exception::system_error,
     517             :                           "signal: floating point divide by zero; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
     518           0 :                           (uintptr_t) m_sig_info->si_addr );
     519           0 :             break;
     520             :         case FPE_FLTOVF:
     521           0 :             report_error( execution_exception::system_error,
     522             :                           "signal: floating point overflow; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
     523           0 :                           (uintptr_t) m_sig_info->si_addr );
     524           0 :             break;
     525             :         case FPE_FLTUND:
     526           0 :             report_error( execution_exception::system_error,
     527             :                           "signal: floating point underflow; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
     528           0 :                           (uintptr_t) m_sig_info->si_addr );
     529           0 :             break;
     530             :         case FPE_FLTRES:
     531           0 :             report_error( execution_exception::system_error,
     532             :                           "signal: floating point inexact result; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
     533           0 :                           (uintptr_t) m_sig_info->si_addr );
     534           0 :             break;
     535             :         case FPE_FLTINV:
     536           0 :             report_error( execution_exception::system_error,
     537             :                           "signal: invalid floating point operation; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
     538           0 :                           (uintptr_t) m_sig_info->si_addr );
     539           0 :             break;
     540             :         case FPE_FLTSUB:
     541           0 :             report_error( execution_exception::system_error,
     542             :                           "signal: subscript out of range; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR,
     543           0 :                           (uintptr_t) m_sig_info->si_addr );
     544           0 :             break;
     545             :         default:
     546           0 :             report_error( execution_exception::system_error,
     547             :                           "signal: SIGFPE, si_code: %d (errnoneous arithmetic operations; address of failing instruction: 0x%" BOOST_TEST_PRIxPTR ")",
     548           0 :                           m_sig_info->si_code, (uintptr_t) m_sig_info->si_addr );
     549           0 :             break;
     550             :         }
     551           0 :         break;
     552             : 
     553             :     case SIGSEGV:
     554           0 :         switch( m_sig_info->si_code ) {
     555             : #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
     556             :         case SEGV_MAPERR:
     557           0 :             report_error( execution_exception::system_fatal_error,
     558             :                           "memory access violation at address: 0x%" BOOST_TEST_PRIxPTR ": no mapping at fault address",
     559           0 :                           (uintptr_t) m_sig_info->si_addr );
     560           0 :             break;
     561             :         case SEGV_ACCERR:
     562           0 :             report_error( execution_exception::system_fatal_error,
     563             :                           "memory access violation at address: 0x%" BOOST_TEST_PRIxPTR ": invalid permissions",
     564           0 :                           (uintptr_t) m_sig_info->si_addr );
     565           0 :             break;
     566             : #endif
     567             :         default:
     568           0 :             report_error( execution_exception::system_fatal_error,
     569             :                           "signal: SIGSEGV, si_code: %d (memory access violation at address: 0x%" BOOST_TEST_PRIxPTR ")",
     570           0 :                           m_sig_info->si_code, (uintptr_t) m_sig_info->si_addr );
     571           0 :             break;
     572             :         }
     573           0 :         break;
     574             : 
     575             :     case SIGBUS:
     576           0 :         switch( m_sig_info->si_code ) {
     577             : #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
     578             :         case BUS_ADRALN:
     579           0 :             report_error( execution_exception::system_fatal_error,
     580             :                           "memory access violation at address: 0x%" BOOST_TEST_PRIxPTR ": invalid address alignment",
     581           0 :                           (uintptr_t) m_sig_info->si_addr );
     582           0 :             break;
     583             :         case BUS_ADRERR:
     584           0 :             report_error( execution_exception::system_fatal_error,
     585             :                           "memory access violation at address: 0x%" BOOST_TEST_PRIxPTR ": non-existent physical address",
     586           0 :                           (uintptr_t) m_sig_info->si_addr );
     587           0 :             break;
     588             :         case BUS_OBJERR:
     589           0 :             report_error( execution_exception::system_fatal_error,
     590             :                           "memory access violation at address: 0x%" BOOST_TEST_PRIxPTR ": object specific hardware error",
     591           0 :                           (uintptr_t) m_sig_info->si_addr );
     592           0 :             break;
     593             : #endif
     594             :         default:
     595           0 :             report_error( execution_exception::system_fatal_error,
     596             :                           "signal: SIGSEGV, si_code: %d (memory access violation at address: 0x%" BOOST_TEST_PRIxPTR ")",
     597           0 :                           m_sig_info->si_code, (uintptr_t) m_sig_info->si_addr );
     598           0 :             break;
     599             :         }
     600           0 :         break;
     601             : 
     602             : #if defined(BOOST_TEST_CATCH_SIGPOLL)
     603             : 
     604             :     case SIGPOLL:
     605             :         switch( m_sig_info->si_code ) {
     606             : #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
     607             :         case POLL_IN:
     608             :             report_error( execution_exception::system_error,
     609             :                           "data input available; band event %d",
     610             :                           (int)m_sig_info->si_band );
     611             :             break;
     612             :         case POLL_OUT:
     613             :             report_error( execution_exception::system_error,
     614             :                           "output buffers available; band event %d",
     615             :                           (int)m_sig_info->si_band );
     616             :             break;
     617             :         case POLL_MSG:
     618             :             report_error( execution_exception::system_error,
     619             :                           "input message available; band event %d",
     620             :                           (int)m_sig_info->si_band );
     621             :             break;
     622             :         case POLL_ERR:
     623             :             report_error( execution_exception::system_error,
     624             :                           "i/o error; band event %d",
     625             :                           (int)m_sig_info->si_band );
     626             :             break;
     627             :         case POLL_PRI:
     628             :             report_error( execution_exception::system_error,
     629             :                           "high priority input available; band event %d",
     630             :                           (int)m_sig_info->si_band );
     631             :             break;
     632             : #if defined(POLL_ERR) && defined(POLL_HUP) && (POLL_ERR - POLL_HUP)
     633             :         case POLL_HUP:
     634             :             report_error( execution_exception::system_error,
     635             :                           "device disconnected; band event %d",
     636             :                           (int)m_sig_info->si_band );
     637             :             break;
     638             : #endif
     639             : #endif
     640             :         default:
     641             :             report_error( execution_exception::system_error,
     642             :                           "signal: SIGPOLL, si_code: %d (asynchronous I/O event occurred; band event %d)",
     643             :                           m_sig_info->si_code, (int)m_sig_info->si_band );
     644             :             break;
     645             :         }
     646             :         break;
     647             : 
     648             : #endif
     649             : 
     650             :     case SIGABRT:
     651           0 :         report_error( execution_exception::system_error,
     652             :                       "signal: SIGABRT (application abort requested)" );
     653           0 :         break;
     654             : 
     655             :     case SIGALRM:
     656           0 :         report_error( execution_exception::timeout_error,
     657             :                       "signal: SIGALRM (timeout while executing function)" );
     658           0 :         break;
     659             : 
     660             :     default:
     661           0 :         report_error( execution_exception::system_error,
     662           0 :                       "unrecognized signal %d", m_sig_info->si_signo );
     663           0 :     }
     664           0 : }
     665             : 
     666             : //____________________________________________________________________________//
     667             : 
     668             : // ************************************************************************** //
     669             : // **************         boost::detail::signal_action         ************** //
     670             : // ************************************************************************** //
     671             : 
     672             : // Forward declaration
     673             : extern "C" {
     674             : static void boost_execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context );
     675             : static void boost_execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context );
     676             : }
     677             : 
     678             : class signal_action {
     679             :     typedef struct sigaction* sigaction_ptr;
     680             : public:
     681             :     //Constructor
     682             :     signal_action();
     683             :     signal_action( int sig, bool install, bool attach_dbg, char* alt_stack );
     684             :     ~signal_action();
     685             : 
     686             : private:
     687             :     // Data members
     688             :     int                 m_sig;
     689             :     bool                m_installed;
     690             :     struct sigaction    m_new_action;
     691             :     struct sigaction    m_old_action;
     692             : };
     693             : 
     694             : //____________________________________________________________________________//
     695             : 
     696        7890 : signal_action::signal_action()
     697        2630 : : m_installed( false )
     698        5260 : {}
     699             : 
     700             : //____________________________________________________________________________//
     701             : 
     702       23670 : signal_action::signal_action( int sig, bool install, bool attach_dbg, char* alt_stack )
     703        7890 : : m_sig( sig )
     704        7890 : , m_installed( install )
     705        7890 : {
     706        7890 :     if( !install )
     707        7160 :         return;
     708             : 
     709         730 :     std::memset( &m_new_action, 0, sizeof(struct sigaction) );
     710             : 
     711         730 :     BOOST_TEST_SYS_ASSERT( ::sigaction( m_sig , sigaction_ptr(), &m_new_action ) != -1 );
     712             : 
     713         730 :     if( m_new_action.sa_sigaction || m_new_action.sa_handler ) {
     714           0 :         m_installed = false;
     715           0 :         return;
     716             :     }
     717             : 
     718         730 :     m_new_action.sa_flags     |= SA_SIGINFO;
     719         730 :     m_new_action.sa_sigaction  = attach_dbg ? &boost_execution_monitor_attaching_signal_handler
     720             :                                             : &boost_execution_monitor_jumping_signal_handler;
     721         730 :     BOOST_TEST_SYS_ASSERT( sigemptyset( &m_new_action.sa_mask ) != -1 );
     722             : 
     723             : #ifdef BOOST_TEST_USE_ALT_STACK
     724         730 :     if( alt_stack )
     725         730 :         m_new_action.sa_flags |= SA_ONSTACK;
     726             : #endif
     727             : 
     728         730 :     BOOST_TEST_SYS_ASSERT( ::sigaction( m_sig, &m_new_action, &m_old_action ) != -1 );
     729       15780 : }
     730             : 
     731             : //____________________________________________________________________________//
     732             : 
     733       21024 : signal_action::~signal_action()
     734       10512 : {
     735       10512 :     if( m_installed )
     736         730 :         ::sigaction( m_sig, &m_old_action , sigaction_ptr() );
     737       21024 : }
     738             : 
     739             : //____________________________________________________________________________//
     740             : 
     741             : // ************************************************************************** //
     742             : // **************        boost::detail::signal_handler         ************** //
     743             : // ************************************************************************** //
     744             : 
     745             : class signal_handler {
     746             : public:
     747             :     // Constructor
     748             :     explicit signal_handler( bool catch_system_errors,
     749             :                              bool detect_fpe,
     750             :                              unsigned long int timeout_microseconds,
     751             :                              bool attach_dbg,
     752             :                              char* alt_stack );
     753             : 
     754             :     // Destructor
     755             :     ~signal_handler();
     756             : 
     757             :     // access methods
     758        1315 :     static sigjmp_buf&      jump_buffer()
     759             :     {
     760        1315 :         assert( !!s_active_handler );
     761             : 
     762        1315 :         return s_active_handler->m_sigjmp_buf;
     763             :     }
     764             : 
     765           0 :     static system_signal_exception&  sys_sig()
     766             :     {
     767           0 :         assert( !!s_active_handler );
     768             : 
     769           0 :         return s_active_handler->m_sys_sig;
     770             :     }
     771             : 
     772             : private:
     773             :     // Data members
     774             :     signal_handler*         m_prev_handler;
     775             :     unsigned long int       m_timeout_microseconds;
     776             : 
     777             :     // Note: We intentionality do not catch SIGCHLD. Users have to deal with it themselves
     778             :     signal_action           m_ILL_action;
     779             :     signal_action           m_FPE_action;
     780             :     signal_action           m_SEGV_action;
     781             :     signal_action           m_BUS_action;
     782             :     signal_action           m_CHLD_action;
     783             :     signal_action           m_POLL_action;
     784             :     signal_action           m_ABRT_action;
     785             :     signal_action           m_ALRM_action;
     786             : 
     787             :     sigjmp_buf              m_sigjmp_buf;
     788             :     system_signal_exception m_sys_sig;
     789             : 
     790             :     static signal_handler*  s_active_handler;
     791             : };
     792             : 
     793             : // !! need to be placed in thread specific storage
     794             : typedef signal_handler* signal_handler_ptr;
     795             : signal_handler* signal_handler::s_active_handler = signal_handler_ptr();
     796             : 
     797             : //____________________________________________________________________________//
     798             : 
     799        5260 : signal_handler::signal_handler( bool catch_system_errors,
     800             :                                 bool detect_fpe,
     801             :                                 unsigned long int timeout_microseconds,
     802             :                                 bool attach_dbg,
     803             :                                 char* alt_stack )
     804        1315 : : m_prev_handler( s_active_handler )
     805        1315 : , m_timeout_microseconds( timeout_microseconds )
     806        1315 : , m_ILL_action ( SIGILL , catch_system_errors,      attach_dbg, alt_stack )
     807        1315 : , m_FPE_action ( SIGFPE , detect_fpe         ,      attach_dbg, alt_stack )
     808        1315 : , m_SEGV_action( SIGSEGV, catch_system_errors,      attach_dbg, alt_stack )
     809        1315 : , m_BUS_action ( SIGBUS , catch_system_errors,      attach_dbg, alt_stack )
     810             : #ifdef BOOST_TEST_CATCH_SIGPOLL
     811             : , m_POLL_action( SIGPOLL, catch_system_errors,      attach_dbg, alt_stack )
     812             : #endif
     813        1315 : , m_ABRT_action( SIGABRT, catch_system_errors,      attach_dbg, alt_stack )
     814        1315 : , m_ALRM_action( SIGALRM, timeout_microseconds > 0, attach_dbg, alt_stack )
     815        1315 : {
     816        1315 :     s_active_handler = this;
     817             : 
     818        1315 :     if( m_timeout_microseconds > 0 ) {
     819           0 :         ::alarm( 0 );
     820           0 :         ::alarm( static_cast<unsigned int>(std::ceil(timeout_microseconds / 1E6) )); // alarm has a precision to the seconds
     821           0 :     }
     822             : 
     823             : #ifdef BOOST_TEST_USE_ALT_STACK
     824        1315 :     if( alt_stack ) {
     825             :         stack_t sigstk;
     826        1315 :         std::memset( &sigstk, 0, sizeof(stack_t) );
     827             : 
     828        1315 :         BOOST_TEST_SYS_ASSERT( ::sigaltstack( 0, &sigstk ) != -1 );
     829             : 
     830        1315 :         if( sigstk.ss_flags & SS_DISABLE ) {
     831        1315 :             sigstk.ss_sp    = alt_stack;
     832        1315 :             sigstk.ss_size  = BOOST_TEST_ALT_STACK_SIZE;
     833        1315 :             sigstk.ss_flags = 0;
     834        1315 :             BOOST_TEST_SYS_ASSERT( ::sigaltstack( &sigstk, 0 ) != -1 );
     835        1315 :         }
     836        1315 :     }
     837             : #endif
     838        2630 : }
     839             : 
     840             : //____________________________________________________________________________//
     841             : 
     842        2628 : signal_handler::~signal_handler()
     843        1314 : {
     844        1314 :     assert( s_active_handler == this );
     845             : 
     846        1314 :     if( m_timeout_microseconds > 0 )
     847           0 :         ::alarm( 0 );
     848             : 
     849             : #ifdef BOOST_TEST_USE_ALT_STACK
     850             : #ifdef __GNUC__
     851             :     // We shouldn't need to explicitly initialize all the members here,
     852             :     // but gcc warns if we don't, so add initializers for each of the
     853             :     // members specified in the POSIX std:
     854        1314 :     stack_t sigstk = { 0, 0, 0 };
     855             : #else
     856             :     stack_t sigstk = { };
     857             : #endif
     858             : 
     859        1314 :     sigstk.ss_size  = MINSIGSTKSZ;
     860        1314 :     sigstk.ss_flags = SS_DISABLE;
     861        1314 :     if( ::sigaltstack( &sigstk, 0 ) == -1 ) {
     862           0 :         int error_n = errno;
     863           0 :         std::cerr << "******** errors disabling the alternate stack:" << std::endl
     864           0 :                   << "\t#error:" << error_n << std::endl
     865           0 :                   << "\t" << std::strerror( error_n ) << std::endl;
     866           0 :     }
     867             : #endif
     868             : 
     869        1314 :     s_active_handler = m_prev_handler;
     870        2628 : }
     871             : 
     872             : //____________________________________________________________________________//
     873             : 
     874             : // ************************************************************************** //
     875             : // **************       execution_monitor_signal_handler       ************** //
     876             : // ************************************************************************** //
     877             : 
     878             : extern "C" {
     879             : 
     880           0 : static void boost_execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context )
     881             : {
     882           0 :     signal_handler::sys_sig()( info, context );
     883             : 
     884           0 :     siglongjmp( signal_handler::jump_buffer(), sig );
     885             : }
     886             : 
     887             : //____________________________________________________________________________//
     888             : 
     889           0 : static void boost_execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context )
     890             : {
     891           0 :     if( !debug::attach_debugger( false ) )
     892           0 :         boost_execution_monitor_jumping_signal_handler( sig, info, context );
     893             : 
     894             :     // debugger attached; it will handle the signal
     895           0 :     BOOST_TEST_SYS_ASSERT( ::signal( sig, SIG_DFL ) != SIG_ERR );
     896           0 : }
     897             : 
     898             : //____________________________________________________________________________//
     899             : 
     900             : }
     901             : 
     902             : } // namespace detail
     903             : 
     904             : // ************************************************************************** //
     905             : // **************        execution_monitor::catch_signals      ************** //
     906             : // ************************************************************************** //
     907             : 
     908             : int
     909        1315 : execution_monitor::catch_signals( boost::function<int ()> const& F )
     910             : {
     911             :     using namespace detail;
     912             : 
     913             : #if defined(__CYGWIN__)
     914             :     p_catch_system_errors.value = false;
     915             : #endif
     916             : 
     917             : #ifdef BOOST_TEST_USE_ALT_STACK
     918        1315 :     if( !!p_use_alt_stack && !m_alt_stack )
     919         292 :         m_alt_stack.reset( new char[BOOST_TEST_ALT_STACK_SIZE] );
     920             : #else
     921             :     p_use_alt_stack.value = false;
     922             : #endif
     923             : 
     924        2630 :     signal_handler local_signal_handler( p_catch_system_errors,
     925        1315 :                                          p_catch_system_errors || (p_detect_fp_exceptions != fpe::BOOST_FPE_OFF),
     926        1315 :                                          p_timeout,
     927        1315 :                                          p_auto_start_dbg,
     928        1315 :                                          !p_use_alt_stack ? 0 : m_alt_stack.get() );
     929             : 
     930        1315 :     if( !sigsetjmp( signal_handler::jump_buffer(), 1 ) )
     931        1315 :         return detail::do_invoke( m_custom_translators , F );
     932             :     else
     933           0 :         BOOST_TEST_I_THROW( local_signal_handler.sys_sig() );
     934        1315 : }
     935             : 
     936             : //____________________________________________________________________________//
     937             : 
     938             : #elif defined(BOOST_SEH_BASED_SIGNAL_HANDLING)
     939             : 
     940             : // ************************************************************************** //
     941             : // **************   Microsoft structured exception handling    ************** //
     942             : // ************************************************************************** //
     943             : 
     944             : #if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0564))
     945             : namespace { void _set_se_translator( void* ) {} }
     946             : #endif
     947             : 
     948             : namespace detail {
     949             : 
     950             : // ************************************************************************** //
     951             : // **************    boost::detail::system_signal_exception    ************** //
     952             : // ************************************************************************** //
     953             : 
     954             : class system_signal_exception {
     955             : public:
     956             :     // Constructor
     957             :     explicit            system_signal_exception( execution_monitor* em )
     958             :     : m_em( em )
     959             :     , m_se_id( 0 )
     960             :     , m_fault_address( 0 )
     961             :     , m_dir( false )
     962             :     , m_timeout( false )
     963             :     {}
     964             : 
     965             :     void                set_timed_out();
     966             :     void                report() const;
     967             :     int                 operator()( unsigned id, _EXCEPTION_POINTERS* exps );
     968             : 
     969             : private:
     970             :     // Data members
     971             :     execution_monitor*  m_em;
     972             : 
     973             :     unsigned            m_se_id;
     974             :     void*               m_fault_address;
     975             :     bool                m_dir;
     976             :     bool                m_timeout;
     977             : };
     978             : 
     979             : //____________________________________________________________________________//
     980             : 
     981             : #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
     982             : static void
     983             : seh_catch_preventer( unsigned /* id */, _EXCEPTION_POINTERS* /* exps */ )
     984             : {
     985             :     throw;
     986             : }
     987             : #endif
     988             : 
     989             : //____________________________________________________________________________//
     990             : 
     991             : void
     992             : system_signal_exception::set_timed_out()
     993             : {
     994             :     m_timeout = true;
     995             : }
     996             : 
     997             : //____________________________________________________________________________//
     998             : 
     999             : 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         730 : execution_monitor::execution_monitor()
    1310         292 : : p_catch_system_errors( true )
    1311         292 : , p_auto_start_dbg( false )
    1312         292 : , p_timeout( 0 )
    1313         292 : , p_use_alt_stack( true )
    1314         292 : , p_detect_fp_exceptions( fpe::BOOST_FPE_OFF )
    1315         438 : {}
    1316             : 
    1317             : //____________________________________________________________________________//
    1318             : 
    1319             : int
    1320        1316 : execution_monitor::execute( boost::function<int ()> const& F )
    1321             : {
    1322        1316 :     if( debug::under_debugger() )
    1323           0 :         p_catch_system_errors.value = false;
    1324             : 
    1325             :     BOOST_TEST_I_TRY {
    1326        1316 :         detail::fpe_except_guard G( p_detect_fp_exceptions );
    1327        1316 :         boost::ignore_unused( G );
    1328             : 
    1329        1315 :         return catch_signals( F );
    1330        1316 :     }
    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           0 :       { detail::report_error( execution_exception::cpp_exception_error,
    1341           0 :                               "C string: %s", ex ); }
    1342             :     catch( std::string const& ex )
    1343           0 :       { detail::report_error( execution_exception::cpp_exception_error,
    1344           0 :                               "std::string: %s", ex.c_str() ); }
    1345             : 
    1346             :     // boost::exception (before std::exception, with extended diagnostic)
    1347             :     catch( boost::exception const& ex )
    1348           0 :       { detail::report_error( execution_exception::cpp_exception_error,
    1349           0 :                               &ex,
    1350           0 :                               "%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           0 :     CATCH_AND_REPORT_STD_EXCEPTION( std::bad_alloc )
    1370           0 :     CATCH_AND_REPORT_STD_EXCEPTION( std::bad_cast )
    1371           0 :     CATCH_AND_REPORT_STD_EXCEPTION( std::bad_typeid )
    1372           0 :     CATCH_AND_REPORT_STD_EXCEPTION( std::bad_exception )
    1373           0 :     CATCH_AND_REPORT_STD_EXCEPTION( std::domain_error )
    1374           0 :     CATCH_AND_REPORT_STD_EXCEPTION( std::invalid_argument )
    1375           0 :     CATCH_AND_REPORT_STD_EXCEPTION( std::length_error )
    1376           0 :     CATCH_AND_REPORT_STD_EXCEPTION( std::out_of_range )
    1377           0 :     CATCH_AND_REPORT_STD_EXCEPTION( std::range_error )
    1378           0 :     CATCH_AND_REPORT_STD_EXCEPTION( std::overflow_error )
    1379           0 :     CATCH_AND_REPORT_STD_EXCEPTION( std::underflow_error )
    1380           0 :     CATCH_AND_REPORT_STD_EXCEPTION( std::logic_error )
    1381           0 :     CATCH_AND_REPORT_STD_EXCEPTION( std::runtime_error )
    1382           0 :     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           0 :       { detail::report_error( execution_exception::cpp_exception_error,
    1388           0 :                               "system_error produced by: %s: %s", ex.p_failed_exp, std::strerror( ex.p_errno ) ); }
    1389             :     catch( detail::system_signal_exception const& ex )
    1390           0 :       { ex.report(); }
    1391             : 
    1392             :     // not an error
    1393             :     catch( execution_aborted const& )
    1394           0 :       { return 0; }
    1395             : 
    1396             :     // just forward
    1397             :     catch( execution_exception const& )
    1398           0 :       { throw; }
    1399             : 
    1400             :     // unknown error
    1401             :     catch( ... )
    1402           0 :       { detail::report_error( execution_exception::cpp_exception_error, "unknown type" ); }
    1403             : 
    1404             : #endif // !BOOST_NO_EXCEPTIONS
    1405             : 
    1406           0 :     BOOST_TEST_UNREACHABLE_RETURN(0);  // never reached; supplied to quiet compiler warnings
    1407        1318 : } // execute
    1408             : 
    1409             : //____________________________________________________________________________//
    1410             : 
    1411             : namespace detail {
    1412             : 
    1413             : struct forward {
    1414        2630 :     explicit    forward( boost::function<void ()> const& F ) : m_F( F ) {}
    1415             : 
    1416        1315 :     int         operator()() { m_F(); return 0; }
    1417             : 
    1418             :     boost::function<void ()> const& m_F;
    1419             : };
    1420             : 
    1421             : } // namespace detail
    1422             : void
    1423        1315 : execution_monitor::vexecute( boost::function<void ()> const& F )
    1424             : {
    1425        1315 :     execute( detail::forward( F ) );
    1426        1315 : }
    1427             : 
    1428             : // ************************************************************************** //
    1429             : // **************                  system_error                ************** //
    1430             : // ************************************************************************** //
    1431             : 
    1432           0 : system_error::system_error( char const* exp )
    1433             : #ifdef UNDER_CE
    1434             : : p_errno( GetLastError() )
    1435             : #else
    1436           0 : : p_errno( errno )
    1437             : #endif
    1438           0 : , p_failed_exp( exp )
    1439           0 : {}
    1440             : 
    1441             : //____________________________________________________________________________//
    1442             : 
    1443             : // ************************************************************************** //
    1444             : // **************              execution_exception             ************** //
    1445             : // ************************************************************************** //
    1446             : 
    1447           0 : execution_exception::execution_exception( error_code ec_, const_string what_msg_, location const& location_ )
    1448           0 : : m_error_code( ec_ )
    1449           0 : , m_what( what_msg_.empty() ? BOOST_TEST_L( "uncaught exception, system error or abort requested" ) : what_msg_ )
    1450           0 : , m_location( location_ )
    1451           0 : {}
    1452             : 
    1453             : //____________________________________________________________________________//
    1454             : 
    1455           0 : execution_exception::location::location( char const* file_name, size_t line_num, char const* func )
    1456           0 : : m_file_name( file_name ? file_name : "unknown location" )
    1457           0 : , m_line_num( line_num )
    1458           0 : , m_function( func )
    1459           0 : {}
    1460             : 
    1461           0 : execution_exception::location::location(const_string file_name, size_t line_num, char const* func )
    1462           0 : : m_file_name( file_name )
    1463           0 : , m_line_num( line_num )
    1464           0 : , m_function( func )
    1465           0 : {}
    1466             : 
    1467             : //____________________________________________________________________________//
    1468             : 
    1469             : // ************************************************************************** //
    1470             : // **************Floating point exception management interface ************** //
    1471             : // ************************************************************************** //
    1472             : 
    1473             : namespace fpe {
    1474             : 
    1475             : unsigned
    1476           0 : enable( unsigned mask )
    1477             : {
    1478           0 :     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           0 :     return BOOST_FPE_OFF;
    1507             : #endif
    1508             : }
    1509             : 
    1510             : //____________________________________________________________________________//
    1511             : 
    1512             : unsigned
    1513        1315 : disable( unsigned mask )
    1514             : {
    1515        1315 :     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        1315 :     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

Generated by: LCOV version 1.16