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)
7 // See http://www.boost.org/libs/test for the library home page.
10 /// Provides execution monitor implementation for all supported
11 /// configurations, including Microsoft structured exception based, unix signals
12 /// based and special workarounds for borland
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.
17 /// Header dependencies are deliberately restricted to reduce coupling to other
19 // ***************************************************************************
21 #ifndef BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER
22 #define BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER
25 #include <boost/test/detail/config.hpp>
26 #include <boost/test/detail/workaround.hpp>
27 #include <boost/test/detail/throw_exception.hpp>
28 #include <boost/test/execution_monitor.hpp>
29 #include <boost/test/debug.hpp>
32 #include <boost/cstdlib.hpp> // for exit codes
33 #include <boost/config.hpp> // for workarounds
34 #include <boost/core/ignore_unused.hpp> // for ignore_unused
35 #ifndef BOOST_NO_EXCEPTIONS
36 #include <boost/exception/get_error_info.hpp> // for get_error_info
37 #include <boost/exception/current_exception_cast.hpp> // for current_exception_cast
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 <cstdarg> // for varargs
52 #include <iostream> // for varargs
54 #ifdef BOOST_NO_STDC_NAMESPACE
55 namespace std { using ::strerror; using ::strlen; using ::strncat; }
59 #if defined(__SUNPRO_CC) || defined(__SunOS)
66 #if defined(__QNXNTO__)
71 #ifdef BOOST_SEH_BASED_SIGNAL_HANDLING
74 # if defined(__MWERKS__) || (defined(_MSC_VER) && !defined(UNDER_CE))
78 # if defined(__BORLANDC__) && __BORLANDC__ >= 0x560 || defined(__MWERKS__)
82 # if defined(__BORLANDC__) && __BORLANDC__ < 0x560
83 typedef unsigned uintptr_t;
86 # if defined(UNDER_CE) && BOOST_WORKAROUND(_MSC_VER, < 1500 )
87 typedef void* uintptr_t;
88 # elif defined(UNDER_CE)
92 # if !defined(NDEBUG) && defined(_MSC_VER) && !defined(UNDER_CE)
94 # define BOOST_TEST_CRT_HOOK_TYPE _CRT_REPORT_HOOK
95 # define BOOST_TEST_CRT_ASSERT _CRT_ASSERT
96 # define BOOST_TEST_CRT_ERROR _CRT_ERROR
97 # define BOOST_TEST_CRT_SET_HOOK(H) _CrtSetReportHook(H)
99 # define BOOST_TEST_CRT_HOOK_TYPE void*
100 # define BOOST_TEST_CRT_ASSERT 2
101 # define BOOST_TEST_CRT_ERROR 1
102 # define BOOST_TEST_CRT_SET_HOOK(H) (void*)(H)
105 # if (!BOOST_WORKAROUND(_MSC_VER, >= 1400 ) && \
106 !defined(BOOST_COMO)) || defined(UNDER_CE)
108 typedef void* _invalid_parameter_handler;
110 inline _invalid_parameter_handler
111 _set_invalid_parameter_handler( _invalid_parameter_handler arg )
118 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564)) || defined(UNDER_CE)
120 namespace { void _set_se_translator( void* ) {} }
124 #elif defined(BOOST_HAS_SIGACTION)
126 # define BOOST_SIGACTION_BASED_SIGNAL_HANDLING
132 # if defined(__FreeBSD__)
134 # include <osreldate.h>
137 # define SIGPOLL SIGIO
140 # if (__FreeBSD_version < 70100)
142 # define ILL_ILLADR 0 // ILL_RESAD_FAULT
143 # define ILL_PRVOPC ILL_PRIVIN_FAULT
144 # define ILL_ILLOPN 2 // ILL_RESOP_FAULT
145 # define ILL_COPROC ILL_FPOP_FAULT
147 # define BOOST_TEST_LIMITED_SIGNAL_DETAILS
152 # if defined(__ANDROID__)
153 # include <android/api-level.h>
156 // documentation of BOOST_TEST_DISABLE_ALT_STACK in execution_monitor.hpp
157 # if !defined(__CYGWIN__) && !defined(__QNXNTO__) && !defined(__bgq__) && \
158 (!defined(__ANDROID__) || __ANDROID_API__ >= 8) && \
159 !defined(BOOST_TEST_DISABLE_ALT_STACK)
160 # define BOOST_TEST_USE_ALT_STACK
163 # if defined(SIGPOLL) && !defined(__CYGWIN__) && \
164 !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) && \
165 !defined(__NetBSD__) && \
167 # define BOOST_TEST_CATCH_SIGPOLL
170 # ifdef BOOST_TEST_USE_ALT_STACK
171 # define BOOST_TEST_ALT_STACK_SIZE SIGSTKSZ
177 # define BOOST_NO_SIGNAL_HANDLING
185 #if !defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
186 # include <boost/core/demangle.hpp>
189 #include <boost/test/detail/suppress_warnings.hpp>
191 //____________________________________________________________________________//
195 // ************************************************************************** //
196 // ************** throw_exception ************** //
197 // ************************************************************************** //
199 #ifdef BOOST_NO_EXCEPTIONS
200 void throw_exception( std::exception const & e ) { abort(); }
203 // ************************************************************************** //
204 // ************** report_error ************** //
205 // ************************************************************************** //
210 # define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) std::vsnprintf( (a1), (a2), (a3), (a4) )
211 #elif BOOST_WORKAROUND(_MSC_VER, <= 1310) || \
212 BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3000)) || \
214 # define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) _vsnprintf( (a1), (a2), (a3), (a4) )
216 # define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) vsnprintf( (a1), (a2), (a3), (a4) )
219 #ifndef BOOST_NO_EXCEPTIONS
221 template <typename ErrorInfo>
222 typename ErrorInfo::value_type
223 extract( boost::exception const* ex )
228 typename ErrorInfo::value_type const * val = boost::get_error_info<ErrorInfo>( *ex );
230 return val ? *val : 0;
233 //____________________________________________________________________________//
236 report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, va_list* args )
238 static const int REPORT_ERROR_BUFFER_SIZE = 4096;
239 static char buf[REPORT_ERROR_BUFFER_SIZE];
241 BOOST_TEST_VSNPRINTF( buf, sizeof(buf)-1, format, *args );
242 buf[sizeof(buf)-1] = 0;
246 BOOST_TEST_I_THROW(execution_exception( ec, buf, execution_exception::location( extract<throw_file>( be ),
247 (size_t)extract<throw_line>( be ),
248 extract<throw_function>( be ) ) ));
251 //____________________________________________________________________________//
254 report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, ... )
257 va_start( args, format );
259 report_error( ec, be, format, &args );
264 //____________________________________________________________________________//
267 report_error( execution_exception::error_code ec, char const* format, ... )
270 va_start( args, format );
272 report_error( ec, 0, format, &args );
275 //____________________________________________________________________________//
277 template<typename Tr,typename Functor>
279 do_invoke( Tr const& tr, Functor const& F )
281 return tr ? (*tr)( F ) : F();
284 //____________________________________________________________________________//
286 struct fpe_except_guard {
287 explicit fpe_except_guard( unsigned detect_fpe )
288 : m_detect_fpe( detect_fpe )
290 // prepare fp exceptions control
291 m_previously_enabled = fpe::disable( fpe::BOOST_FPE_ALL );
292 if( m_previously_enabled != fpe::BOOST_FPE_INV && detect_fpe != fpe::BOOST_FPE_OFF )
293 fpe::enable( detect_fpe );
297 if( m_detect_fpe != fpe::BOOST_FPE_OFF )
298 fpe::disable( m_detect_fpe );
299 if( m_previously_enabled != fpe::BOOST_FPE_INV )
300 fpe::enable( m_previously_enabled );
303 unsigned m_detect_fpe;
304 unsigned m_previously_enabled;
308 // ************************************************************************** //
309 // ************** typeid_name ************** //
310 // ************************************************************************** //
312 #if !defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
315 typeid_name( T const& t )
317 return boost::core::demangle(typeid(t).name());
321 } // namespace detail
323 #if defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING)
325 // ************************************************************************** //
326 // ************** Sigaction based signal handling ************** //
327 // ************************************************************************** //
331 // ************************************************************************** //
332 // ************** boost::detail::system_signal_exception ************** //
333 // ************************************************************************** //
335 class system_signal_exception {
338 system_signal_exception()
344 void operator()( siginfo_t* i, void* c )
353 siginfo_t* m_sig_info; // system signal detailed info
354 void* m_context; // signal context
357 //____________________________________________________________________________//
360 system_signal_exception::report() const
363 return; // no error actually occur?
365 switch( m_sig_info->si_code ) {
367 report_error( execution_exception::system_error,
368 "signal: generated by kill() (or family); uid=%d; pid=%d",
369 (int)m_sig_info->si_uid, (int)m_sig_info->si_pid );
372 report_error( execution_exception::system_error,
373 "signal: sent by sigqueue()" );
376 report_error( execution_exception::system_error,
377 "signal: the expiration of a timer set by timer_settimer()" );
380 report_error( execution_exception::system_error,
381 "signal: generated by the completion of an asynchronous I/O request" );
384 report_error( execution_exception::system_error,
385 "signal: generated by the the arrival of a message on an empty message queue" );
391 switch( m_sig_info->si_signo ) {
393 switch( m_sig_info->si_code ) {
394 #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
396 report_error( execution_exception::system_fatal_error,
397 "signal: illegal opcode; address of failing instruction: 0x%08lx",
398 m_sig_info->si_addr );
401 report_error( execution_exception::system_fatal_error,
402 "signal: illegal trap; address of failing instruction: 0x%08lx",
403 m_sig_info->si_addr );
406 report_error( execution_exception::system_fatal_error,
407 "signal: privileged register; address of failing instruction: 0x%08lx",
408 m_sig_info->si_addr );
411 report_error( execution_exception::system_fatal_error,
412 "signal: internal stack error; address of failing instruction: 0x%08lx",
413 m_sig_info->si_addr );
417 report_error( execution_exception::system_fatal_error,
418 "signal: illegal operand; address of failing instruction: 0x%08lx",
419 m_sig_info->si_addr );
422 report_error( execution_exception::system_fatal_error,
423 "signal: illegal addressing mode; address of failing instruction: 0x%08lx",
424 m_sig_info->si_addr );
427 report_error( execution_exception::system_fatal_error,
428 "signal: privileged opcode; address of failing instruction: 0x%08lx",
429 m_sig_info->si_addr );
432 report_error( execution_exception::system_fatal_error,
433 "signal: co-processor error; address of failing instruction: 0x%08lx",
434 m_sig_info->si_addr );
437 report_error( execution_exception::system_fatal_error,
438 "signal: SIGILL, si_code: %d (illegal instruction; address of failing instruction: 0x%08lx)",
439 m_sig_info->si_addr, m_sig_info->si_code );
445 switch( m_sig_info->si_code ) {
447 report_error( execution_exception::system_error,
448 "signal: integer divide by zero; address of failing instruction: 0x%08lx",
449 m_sig_info->si_addr );
452 report_error( execution_exception::system_error,
453 "signal: integer overflow; address of failing instruction: 0x%08lx",
454 m_sig_info->si_addr );
457 report_error( execution_exception::system_error,
458 "signal: floating point divide by zero; address of failing instruction: 0x%08lx",
459 m_sig_info->si_addr );
462 report_error( execution_exception::system_error,
463 "signal: floating point overflow; address of failing instruction: 0x%08lx",
464 m_sig_info->si_addr );
467 report_error( execution_exception::system_error,
468 "signal: floating point underflow; address of failing instruction: 0x%08lx",
469 m_sig_info->si_addr );
472 report_error( execution_exception::system_error,
473 "signal: floating point inexact result; address of failing instruction: 0x%08lx",
474 m_sig_info->si_addr );
477 report_error( execution_exception::system_error,
478 "signal: invalid floating point operation; address of failing instruction: 0x%08lx",
479 m_sig_info->si_addr );
482 report_error( execution_exception::system_error,
483 "signal: subscript out of range; address of failing instruction: 0x%08lx",
484 m_sig_info->si_addr );
487 report_error( execution_exception::system_error,
488 "signal: SIGFPE, si_code: %d (errnoneous arithmetic operations; address of failing instruction: 0x%08lx)",
489 m_sig_info->si_addr, m_sig_info->si_code );
495 switch( m_sig_info->si_code ) {
496 #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
498 report_error( execution_exception::system_fatal_error,
499 "memory access violation at address: 0x%08lx: no mapping at fault address",
500 m_sig_info->si_addr );
503 report_error( execution_exception::system_fatal_error,
504 "memory access violation at address: 0x%08lx: invalid permissions",
505 m_sig_info->si_addr );
509 report_error( execution_exception::system_fatal_error,
510 "signal: SIGSEGV, si_code: %d (memory access violation at address: 0x%08lx)",
511 m_sig_info->si_addr, m_sig_info->si_code );
517 switch( m_sig_info->si_code ) {
518 #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
520 report_error( execution_exception::system_fatal_error,
521 "memory access violation at address: 0x%08lx: invalid address alignment",
522 m_sig_info->si_addr );
525 report_error( execution_exception::system_fatal_error,
526 "memory access violation at address: 0x%08lx: non-existent physical address",
527 m_sig_info->si_addr );
530 report_error( execution_exception::system_fatal_error,
531 "memory access violation at address: 0x%08lx: object specific hardware error",
532 m_sig_info->si_addr );
536 report_error( execution_exception::system_fatal_error,
537 "signal: SIGSEGV, si_code: %d (memory access violation at address: 0x%08lx)",
538 m_sig_info->si_addr, m_sig_info->si_code );
543 #if defined(BOOST_TEST_CATCH_SIGPOLL)
546 switch( m_sig_info->si_code ) {
547 #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
549 report_error( execution_exception::system_error,
550 "data input available; band event %d",
551 (int)m_sig_info->si_band );
554 report_error( execution_exception::system_error,
555 "output buffers available; band event %d",
556 (int)m_sig_info->si_band );
559 report_error( execution_exception::system_error,
560 "input message available; band event %d",
561 (int)m_sig_info->si_band );
564 report_error( execution_exception::system_error,
565 "i/o error; band event %d",
566 (int)m_sig_info->si_band );
569 report_error( execution_exception::system_error,
570 "high priority input available; band event %d",
571 (int)m_sig_info->si_band );
573 #if defined(POLL_ERR) && defined(POLL_HUP) && (POLL_ERR - POLL_HUP)
575 report_error( execution_exception::system_error,
576 "device disconnected; band event %d",
577 (int)m_sig_info->si_band );
582 report_error( execution_exception::system_error,
583 "signal: SIGPOLL, si_code: %d (asynchronous I/O event occurred; band event %d)",
584 (int)m_sig_info->si_band, m_sig_info->si_code );
592 report_error( execution_exception::system_error,
593 "signal: SIGABRT (application abort requested)" );
597 report_error( execution_exception::timeout_error,
598 "signal: SIGALRM (timeout while executing function)" );
602 report_error( execution_exception::system_error,
603 "unrecognized signal %d", m_sig_info->si_signo );
607 //____________________________________________________________________________//
609 // ************************************************************************** //
610 // ************** boost::detail::signal_action ************** //
611 // ************************************************************************** //
613 // Forward declaration
615 static void boost_execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context );
616 static void boost_execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context );
619 class signal_action {
620 typedef struct sigaction* sigaction_ptr;
624 signal_action( int sig, bool install, bool attach_dbg, char* alt_stack );
631 struct sigaction m_new_action;
632 struct sigaction m_old_action;
635 //____________________________________________________________________________//
637 signal_action::signal_action()
638 : m_installed( false )
641 //____________________________________________________________________________//
643 signal_action::signal_action( int sig, bool install, bool attach_dbg, char* alt_stack )
645 , m_installed( install )
650 std::memset( &m_new_action, 0, sizeof(struct sigaction) );
652 BOOST_TEST_SYS_ASSERT( ::sigaction( m_sig , sigaction_ptr(), &m_new_action ) != -1 );
654 if( m_new_action.sa_sigaction || m_new_action.sa_handler ) {
659 m_new_action.sa_flags |= SA_SIGINFO;
660 m_new_action.sa_sigaction = attach_dbg ? &boost_execution_monitor_attaching_signal_handler
661 : &boost_execution_monitor_jumping_signal_handler;
662 BOOST_TEST_SYS_ASSERT( sigemptyset( &m_new_action.sa_mask ) != -1 );
664 #ifdef BOOST_TEST_USE_ALT_STACK
666 m_new_action.sa_flags |= SA_ONSTACK;
669 BOOST_TEST_SYS_ASSERT( ::sigaction( m_sig, &m_new_action, &m_old_action ) != -1 );
672 //____________________________________________________________________________//
674 signal_action::~signal_action()
677 ::sigaction( m_sig, &m_old_action , sigaction_ptr() );
680 //____________________________________________________________________________//
682 // ************************************************************************** //
683 // ************** boost::detail::signal_handler ************** //
684 // ************************************************************************** //
686 class signal_handler {
689 explicit signal_handler( bool catch_system_errors, bool detect_fpe, unsigned timeout, bool attach_dbg, char* alt_stack );
695 static sigjmp_buf& jump_buffer()
697 assert( !!s_active_handler );
699 return s_active_handler->m_sigjmp_buf;
702 static system_signal_exception& sys_sig()
704 assert( !!s_active_handler );
706 return s_active_handler->m_sys_sig;
711 signal_handler* m_prev_handler;
714 // Note: We intentionality do not catch SIGCHLD. Users have to deal with it themselves
715 signal_action m_ILL_action;
716 signal_action m_FPE_action;
717 signal_action m_SEGV_action;
718 signal_action m_BUS_action;
719 signal_action m_CHLD_action;
720 signal_action m_POLL_action;
721 signal_action m_ABRT_action;
722 signal_action m_ALRM_action;
724 sigjmp_buf m_sigjmp_buf;
725 system_signal_exception m_sys_sig;
727 static signal_handler* s_active_handler;
730 // !! need to be placed in thread specific storage
731 typedef signal_handler* signal_handler_ptr;
732 signal_handler* signal_handler::s_active_handler = signal_handler_ptr();
734 //____________________________________________________________________________//
736 signal_handler::signal_handler( bool catch_system_errors, bool detect_fpe, unsigned timeout, bool attach_dbg, char* alt_stack )
737 : m_prev_handler( s_active_handler )
738 , m_timeout( timeout )
739 , m_ILL_action ( SIGILL , catch_system_errors, attach_dbg, alt_stack )
740 , m_FPE_action ( SIGFPE , detect_fpe , attach_dbg, alt_stack )
741 , m_SEGV_action( SIGSEGV, catch_system_errors, attach_dbg, alt_stack )
742 , m_BUS_action ( SIGBUS , catch_system_errors, attach_dbg, alt_stack )
743 #ifdef BOOST_TEST_CATCH_SIGPOLL
744 , m_POLL_action( SIGPOLL, catch_system_errors, attach_dbg, alt_stack )
746 , m_ABRT_action( SIGABRT, catch_system_errors, attach_dbg, alt_stack )
747 , m_ALRM_action( SIGALRM, timeout > 0 , attach_dbg, alt_stack )
749 s_active_handler = this;
751 if( m_timeout > 0 ) {
756 #ifdef BOOST_TEST_USE_ALT_STACK
759 std::memset( &sigstk, 0, sizeof(stack_t) );
761 BOOST_TEST_SYS_ASSERT( ::sigaltstack( 0, &sigstk ) != -1 );
763 if( sigstk.ss_flags & SS_DISABLE ) {
764 sigstk.ss_sp = alt_stack;
765 sigstk.ss_size = BOOST_TEST_ALT_STACK_SIZE;
767 BOOST_TEST_SYS_ASSERT( ::sigaltstack( &sigstk, 0 ) != -1 );
773 //____________________________________________________________________________//
775 signal_handler::~signal_handler()
777 assert( s_active_handler == this );
782 #ifdef BOOST_TEST_USE_ALT_STACK
784 // We shouldn't need to explicitly initialize all the members here,
785 // but gcc warns if we don't, so add initializers for each of the
786 // members specified in the POSIX std:
787 stack_t sigstk = { 0, 0, 0 };
789 stack_t sigstk = { };
792 sigstk.ss_size = MINSIGSTKSZ;
793 sigstk.ss_flags = SS_DISABLE;
794 if( ::sigaltstack( &sigstk, 0 ) == -1 ) {
796 std::cerr << "******** errors disabling the alternate stack:" << std::endl
797 << "\t#error:" << error_n << std::endl
798 << "\t" << std::strerror( error_n ) << std::endl;
802 s_active_handler = m_prev_handler;
805 //____________________________________________________________________________//
807 // ************************************************************************** //
808 // ************** execution_monitor_signal_handler ************** //
809 // ************************************************************************** //
813 static void boost_execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context )
815 signal_handler::sys_sig()( info, context );
817 siglongjmp( signal_handler::jump_buffer(), sig );
820 //____________________________________________________________________________//
822 static void boost_execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context )
824 if( !debug::attach_debugger( false ) )
825 boost_execution_monitor_jumping_signal_handler( sig, info, context );
827 // debugger attached; it will handle the signal
828 BOOST_TEST_SYS_ASSERT( ::signal( sig, SIG_DFL ) != SIG_ERR );
831 //____________________________________________________________________________//
835 } // namespace detail
837 // ************************************************************************** //
838 // ************** execution_monitor::catch_signals ************** //
839 // ************************************************************************** //
842 execution_monitor::catch_signals( boost::function<int ()> const& F )
844 using namespace detail;
846 #if defined(__CYGWIN__)
847 p_catch_system_errors.value = false;
850 #ifdef BOOST_TEST_USE_ALT_STACK
851 if( !!p_use_alt_stack && !m_alt_stack )
852 m_alt_stack.reset( new char[BOOST_TEST_ALT_STACK_SIZE] );
854 p_use_alt_stack.value = false;
857 signal_handler local_signal_handler( p_catch_system_errors,
858 p_catch_system_errors || (p_detect_fp_exceptions != fpe::BOOST_FPE_OFF),
861 !p_use_alt_stack ? 0 : m_alt_stack.get() );
863 if( !sigsetjmp( signal_handler::jump_buffer(), 1 ) )
864 return detail::do_invoke( m_custom_translators , F );
866 BOOST_TEST_I_THROW( local_signal_handler.sys_sig() );
869 //____________________________________________________________________________//
871 #elif defined(BOOST_SEH_BASED_SIGNAL_HANDLING)
873 // ************************************************************************** //
874 // ************** Microsoft structured exception handling ************** //
875 // ************************************************************************** //
877 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
878 namespace { void _set_se_translator( void* ) {} }
883 // ************************************************************************** //
884 // ************** boost::detail::system_signal_exception ************** //
885 // ************************************************************************** //
887 class system_signal_exception {
890 explicit system_signal_exception( execution_monitor* em )
893 , m_fault_address( 0 )
898 int operator()( unsigned id, _EXCEPTION_POINTERS* exps );
902 execution_monitor* m_em;
905 void* m_fault_address;
909 //____________________________________________________________________________//
911 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
913 seh_catch_preventer( unsigned /* id */, _EXCEPTION_POINTERS* /* exps */ )
919 //____________________________________________________________________________//
922 system_signal_exception::operator()( unsigned id, _EXCEPTION_POINTERS* exps )
924 const unsigned MSFT_CPP_EXCEPT = 0xE06d7363; // EMSC
926 // C++ exception - allow to go through
927 if( id == MSFT_CPP_EXCEPT )
928 return EXCEPTION_CONTINUE_SEARCH;
930 // FPE detection is enabled, while system exception detection is not - check if this is actually FPE
931 if( !m_em->p_catch_system_errors ) {
932 if( !m_em->p_detect_fp_exceptions )
933 return EXCEPTION_CONTINUE_SEARCH;
936 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
937 case EXCEPTION_FLT_STACK_CHECK:
938 case EXCEPTION_FLT_DENORMAL_OPERAND:
939 case EXCEPTION_FLT_INEXACT_RESULT:
940 case EXCEPTION_FLT_OVERFLOW:
941 case EXCEPTION_FLT_UNDERFLOW:
942 case EXCEPTION_FLT_INVALID_OPERATION:
943 case STATUS_FLOAT_MULTIPLE_FAULTS:
944 case STATUS_FLOAT_MULTIPLE_TRAPS:
947 return EXCEPTION_CONTINUE_SEARCH;
951 if( !!m_em->p_auto_start_dbg && debug::attach_debugger( false ) ) {
952 m_em->p_catch_system_errors.value = false;
953 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
954 _set_se_translator( &seh_catch_preventer );
956 return EXCEPTION_CONTINUE_EXECUTION;
960 if( m_se_id == EXCEPTION_ACCESS_VIOLATION && exps->ExceptionRecord->NumberParameters == 2 ) {
961 m_fault_address = (void*)exps->ExceptionRecord->ExceptionInformation[1];
962 m_dir = exps->ExceptionRecord->ExceptionInformation[0] == 0;
965 return EXCEPTION_EXECUTE_HANDLER;
968 //____________________________________________________________________________//
971 system_signal_exception::report() const
974 // cases classified as system_fatal_error
975 case EXCEPTION_ACCESS_VIOLATION: {
976 if( !m_fault_address )
977 detail::report_error( execution_exception::system_fatal_error, "memory access violation" );
979 detail::report_error(
980 execution_exception::system_fatal_error,
981 "memory access violation occurred at address 0x%08lx, while attempting to %s",
983 m_dir ? " read inaccessible data"
984 : " write to an inaccessible (or protected) address"
989 case EXCEPTION_ILLEGAL_INSTRUCTION:
990 detail::report_error( execution_exception::system_fatal_error, "illegal instruction" );
993 case EXCEPTION_PRIV_INSTRUCTION:
994 detail::report_error( execution_exception::system_fatal_error, "tried to execute an instruction whose operation is not allowed in the current machine mode" );
997 case EXCEPTION_IN_PAGE_ERROR:
998 detail::report_error( execution_exception::system_fatal_error, "access to a memory page that is not present" );
1001 case EXCEPTION_STACK_OVERFLOW:
1002 detail::report_error( execution_exception::system_fatal_error, "stack overflow" );
1005 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
1006 detail::report_error( execution_exception::system_fatal_error, "tried to continue execution after a non continuable exception occurred" );
1009 // cases classified as (non-fatal) system_trap
1010 case EXCEPTION_DATATYPE_MISALIGNMENT:
1011 detail::report_error( execution_exception::system_error, "data misalignment" );
1014 case EXCEPTION_INT_DIVIDE_BY_ZERO:
1015 detail::report_error( execution_exception::system_error, "integer divide by zero" );
1018 case EXCEPTION_INT_OVERFLOW:
1019 detail::report_error( execution_exception::system_error, "integer overflow" );
1022 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1023 detail::report_error( execution_exception::system_error, "array bounds exceeded" );
1026 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
1027 detail::report_error( execution_exception::system_error, "floating point divide by zero" );
1030 case EXCEPTION_FLT_STACK_CHECK:
1031 detail::report_error( execution_exception::system_error,
1032 "stack overflowed or underflowed as the result of a floating-point operation" );
1035 case EXCEPTION_FLT_DENORMAL_OPERAND:
1036 detail::report_error( execution_exception::system_error,
1037 "operand of floating point operation is denormal" );
1040 case EXCEPTION_FLT_INEXACT_RESULT:
1041 detail::report_error( execution_exception::system_error,
1042 "result of a floating-point operation cannot be represented exactly" );
1045 case EXCEPTION_FLT_OVERFLOW:
1046 detail::report_error( execution_exception::system_error,
1047 "exponent of a floating-point operation is greater than the magnitude allowed by the corresponding type" );
1050 case EXCEPTION_FLT_UNDERFLOW:
1051 detail::report_error( execution_exception::system_error,
1052 "exponent of a floating-point operation is less than the magnitude allowed by the corresponding type" );
1055 case EXCEPTION_FLT_INVALID_OPERATION:
1056 detail::report_error( execution_exception::system_error, "floating point error" );
1059 case STATUS_FLOAT_MULTIPLE_FAULTS:
1060 detail::report_error( execution_exception::system_error, "multiple floating point errors" );
1063 case STATUS_FLOAT_MULTIPLE_TRAPS:
1064 detail::report_error( execution_exception::system_error, "multiple floating point errors" );
1067 case EXCEPTION_BREAKPOINT:
1068 detail::report_error( execution_exception::system_error, "breakpoint encountered" );
1072 detail::report_error( execution_exception::system_error, "unrecognized exception. Id: 0x%08lx", m_se_id );
1077 //____________________________________________________________________________//
1079 // ************************************************************************** //
1080 // ************** assert_reporting_function ************** //
1081 // ************************************************************************** //
1083 int BOOST_TEST_CALL_DECL
1084 assert_reporting_function( int reportType, char* userMessage, int* )
1086 // write this way instead of switch to avoid unreachable statements
1087 if( reportType == BOOST_TEST_CRT_ASSERT || reportType == BOOST_TEST_CRT_ERROR )
1088 detail::report_error( reportType == BOOST_TEST_CRT_ASSERT ? execution_exception::user_error : execution_exception::system_error, userMessage );
1091 } // assert_reporting_function
1093 //____________________________________________________________________________//
1095 void BOOST_TEST_CALL_DECL
1096 invalid_param_handler( wchar_t const* /* expr */,
1097 wchar_t const* /* func */,
1098 wchar_t const* /* file */,
1099 unsigned /* line */,
1100 uintptr_t /* reserved */)
1102 detail::report_error( execution_exception::user_error,
1103 "Invalid parameter detected by C runtime library" );
1106 //____________________________________________________________________________//
1108 } // namespace detail
1110 // ************************************************************************** //
1111 // ************** execution_monitor::catch_signals ************** //
1112 // ************************************************************************** //
1115 execution_monitor::catch_signals( boost::function<int ()> const& F )
1117 _invalid_parameter_handler old_iph = _invalid_parameter_handler();
1118 BOOST_TEST_CRT_HOOK_TYPE old_crt_hook = 0;
1120 if( p_catch_system_errors ) {
1121 old_crt_hook = BOOST_TEST_CRT_SET_HOOK( &detail::assert_reporting_function );
1123 old_iph = _set_invalid_parameter_handler(
1124 reinterpret_cast<_invalid_parameter_handler>( &detail::invalid_param_handler ) );
1125 } else if( !p_detect_fp_exceptions ) {
1126 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
1127 _set_se_translator( &detail::seh_catch_preventer );
1131 detail::system_signal_exception SSE( this );
1134 // clang windows workaround: this not available in __finally scope
1135 bool l_catch_system_errors = p_catch_system_errors;
1139 ret_val = detail::do_invoke( m_custom_translators, F );
1141 __except( SSE( GetExceptionCode(), GetExceptionInformation() ) ) {
1146 if( l_catch_system_errors ) {
1147 BOOST_TEST_CRT_SET_HOOK( old_crt_hook );
1149 _set_invalid_parameter_handler( old_iph );
1156 //____________________________________________________________________________//
1158 #else // default signal handler
1162 class system_signal_exception {
1164 void report() const {}
1167 } // namespace detail
1170 execution_monitor::catch_signals( boost::function<int ()> const& F )
1172 return detail::do_invoke( m_custom_translators , F );
1175 //____________________________________________________________________________//
1177 #endif // choose signal handler
1179 // ************************************************************************** //
1180 // ************** execution_monitor ************** //
1181 // ************************************************************************** //
1183 execution_monitor::execution_monitor()
1184 : p_catch_system_errors( true )
1185 , p_auto_start_dbg( false )
1187 , p_use_alt_stack( true )
1188 , p_detect_fp_exceptions( fpe::BOOST_FPE_OFF )
1191 //____________________________________________________________________________//
1194 execution_monitor::execute( boost::function<int ()> const& F )
1196 if( debug::under_debugger() )
1197 p_catch_system_errors.value = false;
1200 detail::fpe_except_guard G( p_detect_fp_exceptions );
1201 unit_test::ut_detail::ignore_unused_variable_warning( G );
1203 return catch_signals( F );
1206 #ifndef BOOST_NO_EXCEPTIONS
1208 // Catch-clause reference arguments are a bit different from function
1209 // arguments (ISO 15.3 paragraphs 18 & 19). Apparently const isn't
1210 // required. Programmers ask for const anyhow, so we supply it. That's
1211 // easier than answering questions about non-const usage.
1213 catch( char const* ex )
1214 { detail::report_error( execution_exception::cpp_exception_error,
1215 "C string: %s", ex ); }
1216 catch( std::string const& ex )
1217 { detail::report_error( execution_exception::cpp_exception_error,
1218 "std::string: %s", ex.c_str() ); }
1221 #if defined(BOOST_NO_TYPEID) || defined(BOOST_NO_RTTI)
1222 #define CATCH_AND_REPORT_STD_EXCEPTION( ex_name ) \
1223 catch( ex_name const& ex ) \
1224 { detail::report_error( execution_exception::cpp_exception_error, \
1225 current_exception_cast<boost::exception const>(), \
1226 #ex_name ": %s", ex.what() ); } \
1229 #define CATCH_AND_REPORT_STD_EXCEPTION( ex_name ) \
1230 catch( ex_name const& ex ) \
1231 { detail::report_error( execution_exception::cpp_exception_error, \
1232 current_exception_cast<boost::exception const>(), \
1233 "%s: %s", detail::typeid_name(ex).c_str(), ex.what() ); } \
1237 CATCH_AND_REPORT_STD_EXCEPTION( std::bad_alloc )
1239 #if BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
1240 CATCH_AND_REPORT_STD_EXCEPTION( std::bad_cast )
1241 CATCH_AND_REPORT_STD_EXCEPTION( std::bad_typeid )
1243 CATCH_AND_REPORT_STD_EXCEPTION( std::bad_cast )
1244 CATCH_AND_REPORT_STD_EXCEPTION( std::bad_typeid )
1247 CATCH_AND_REPORT_STD_EXCEPTION( std::bad_exception )
1248 CATCH_AND_REPORT_STD_EXCEPTION( std::domain_error )
1249 CATCH_AND_REPORT_STD_EXCEPTION( std::invalid_argument )
1250 CATCH_AND_REPORT_STD_EXCEPTION( std::length_error )
1251 CATCH_AND_REPORT_STD_EXCEPTION( std::out_of_range )
1252 CATCH_AND_REPORT_STD_EXCEPTION( std::range_error )
1253 CATCH_AND_REPORT_STD_EXCEPTION( std::overflow_error )
1254 CATCH_AND_REPORT_STD_EXCEPTION( std::underflow_error )
1255 CATCH_AND_REPORT_STD_EXCEPTION( std::logic_error )
1256 CATCH_AND_REPORT_STD_EXCEPTION( std::runtime_error )
1257 CATCH_AND_REPORT_STD_EXCEPTION( std::exception )
1258 #undef CATCH_AND_REPORT_STD_EXCEPTION
1260 catch( boost::exception const& ex )
1261 { detail::report_error( execution_exception::cpp_exception_error,
1263 #if defined(BOOST_NO_TYPEID) || defined(BOOST_NO_RTTI)
1264 "unknown boost::exception" ); }
1266 typeid(ex).name() ); }
1270 catch( system_error const& ex )
1271 { detail::report_error( execution_exception::cpp_exception_error,
1272 "system_error produced by: %s: %s", ex.p_failed_exp, std::strerror( ex.p_errno ) ); }
1273 catch( detail::system_signal_exception const& ex )
1277 catch( execution_aborted const& )
1281 catch( execution_exception const& )
1286 { detail::report_error( execution_exception::cpp_exception_error, "unknown type" ); }
1288 #endif // !BOOST_NO_EXCEPTIONS
1290 return 0; // never reached; supplied to quiet compiler warnings
1293 //____________________________________________________________________________//
1298 explicit forward( boost::function<void ()> const& F ) : m_F( F ) {}
1300 int operator()() { m_F(); return 0; }
1302 boost::function<void ()> const& m_F;
1305 } // namespace detail
1307 execution_monitor::vexecute( boost::function<void ()> const& F )
1309 execute( detail::forward( F ) );
1312 // ************************************************************************** //
1313 // ************** system_error ************** //
1314 // ************************************************************************** //
1316 system_error::system_error( char const* exp )
1318 : p_errno( GetLastError() )
1322 , p_failed_exp( exp )
1325 //____________________________________________________________________________//
1327 // ************************************************************************** //
1328 // ************** execution_exception ************** //
1329 // ************************************************************************** //
1331 execution_exception::execution_exception( error_code ec_, const_string what_msg_, location const& location_ )
1332 : m_error_code( ec_ )
1333 , m_what( what_msg_.empty() ? BOOST_TEST_L( "uncaught exception, system error or abort requested" ) : what_msg_ )
1334 , m_location( location_ )
1337 //____________________________________________________________________________//
1339 execution_exception::location::location( char const* file_name, size_t line_num, char const* func )
1340 : m_file_name( file_name ? file_name : "unknown location" )
1341 , m_line_num( line_num )
1342 , m_function( func )
1345 execution_exception::location::location(const_string file_name, size_t line_num, char const* func )
1346 : m_file_name( file_name )
1347 , m_line_num( line_num )
1348 , m_function( func )
1351 //____________________________________________________________________________//
1353 // ************************************************************************** //
1354 // **************Floating point exception management interface ************** //
1355 // ************************************************************************** //
1360 enable( unsigned mask )
1362 boost::ignore_unused(mask);
1363 #if defined(BOOST_TEST_FPE_SUPPORT_WITH_SEH__)
1366 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
1367 unsigned old_cw = ::_controlfp( 0, 0 );
1368 ::_controlfp( old_cw & ~mask, BOOST_FPE_ALL );
1371 if( ::_controlfp_s( &old_cw, 0, 0 ) != 0 )
1372 return BOOST_FPE_INV;
1374 // Set the control word
1375 if( ::_controlfp_s( 0, old_cw & ~mask, BOOST_FPE_ALL ) != 0 )
1376 return BOOST_FPE_INV;
1378 return ~old_cw & BOOST_FPE_ALL;
1380 #elif defined(BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__)
1381 // same macro definition as in execution_monitor.hpp
1382 if (BOOST_FPE_ALL == BOOST_FPE_OFF)
1383 /* Not Implemented */
1384 return BOOST_FPE_OFF;
1385 feclearexcept(BOOST_FPE_ALL);
1386 int res = feenableexcept( mask );
1387 return res == -1 ? (unsigned)BOOST_FPE_INV : (unsigned)res;
1389 /* Not Implemented */
1390 return BOOST_FPE_OFF;
1394 //____________________________________________________________________________//
1397 disable( unsigned mask )
1399 boost::ignore_unused(mask);
1401 #if defined(BOOST_TEST_FPE_SUPPORT_WITH_SEH__)
1403 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
1404 unsigned old_cw = ::_controlfp( 0, 0 );
1405 ::_controlfp( old_cw | mask, BOOST_FPE_ALL );
1408 if( ::_controlfp_s( &old_cw, 0, 0 ) != 0 )
1409 return BOOST_FPE_INV;
1411 // Set the control word
1412 if( ::_controlfp_s( 0, old_cw | mask, BOOST_FPE_ALL ) != 0 )
1413 return BOOST_FPE_INV;
1415 return ~old_cw & BOOST_FPE_ALL;
1417 #elif defined(BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__)
1418 if (BOOST_FPE_ALL == BOOST_FPE_OFF)
1419 /* Not Implemented */
1420 return BOOST_FPE_INV;
1421 feclearexcept(BOOST_FPE_ALL);
1422 int res = fedisableexcept( mask );
1423 return res == -1 ? (unsigned)BOOST_FPE_INV : (unsigned)res;
1425 /* Not Implemented */
1426 return BOOST_FPE_INV;
1430 //____________________________________________________________________________//
1434 } // namespace boost
1436 #include <boost/test/detail/enable_warnings.hpp>
1438 #endif // BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER