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.
11 // Version : $Revision$
13 // Description : provides execution monitor implementation for all supported
14 // configurations, including Microsoft structured exception based, unix signals
15 // based and special workarounds for borland
17 // Note that when testing requirements or user wishes preclude use of this
18 // file as a separate compilation unit, it may be included as a header file.
20 // Header dependencies are deliberately restricted to reduce coupling to other
22 // ***************************************************************************
24 #ifndef BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER
25 #define BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER
28 #include <boost/test/detail/config.hpp>
29 #include <boost/test/detail/workaround.hpp>
30 #include <boost/test/detail/throw_exception.hpp>
31 #include <boost/test/execution_monitor.hpp>
32 #include <boost/test/debug.hpp>
35 #include <boost/cstdlib.hpp> // for exit codes
36 #include <boost/config.hpp> // for workarounds
37 #include <boost/core/ignore_unused.hpp> // for ignore_unused
38 #ifndef BOOST_NO_EXCEPTION
39 #include <boost/exception/get_error_info.hpp> // for get_error_info
40 #include <boost/exception/current_exception_cast.hpp> // for current_exception_cast
44 #include <string> // for std::string
45 #include <new> // for std::bad_alloc
46 #include <typeinfo> // for std::bad_cast, std::bad_typeid
47 #include <exception> // for std::exception, std::bad_exception
48 #include <stdexcept> // for std exception hierarchy
49 #include <cstring> // for C string API
50 #include <cassert> // for assert
51 #include <cstddef> // for NULL
52 #include <cstdio> // for vsnprintf
53 #include <cstdarg> // for varargs
55 #include <iostream> // for varargs
57 #ifdef BOOST_NO_STDC_NAMESPACE
58 namespace std { using ::strerror; using ::strlen; using ::strncat; }
62 #if defined(__SUNPRO_CC) || defined(__SunOS)
69 #if defined(__QNXNTO__)
74 #ifdef BOOST_SEH_BASED_SIGNAL_HANDLING
77 # if defined(__MWERKS__) || (defined(_MSC_VER) && !defined(UNDER_CE))
81 # if defined(__BORLANDC__) && __BORLANDC__ >= 0x560 || defined(__MWERKS__)
85 # if defined(__BORLANDC__) && __BORLANDC__ < 0x560
86 typedef unsigned uintptr_t;
89 # if defined(UNDER_CE) && BOOST_WORKAROUND(_MSC_VER, < 1500 )
90 typedef void* uintptr_t;
91 # elif defined(UNDER_CE)
95 # if !defined(NDEBUG) && defined(_MSC_VER) && !defined(UNDER_CE)
97 # define BOOST_TEST_CRT_HOOK_TYPE _CRT_REPORT_HOOK
98 # define BOOST_TEST_CRT_ASSERT _CRT_ASSERT
99 # define BOOST_TEST_CRT_ERROR _CRT_ERROR
100 # define BOOST_TEST_CRT_SET_HOOK(H) _CrtSetReportHook(H)
102 # define BOOST_TEST_CRT_HOOK_TYPE void*
103 # define BOOST_TEST_CRT_ASSERT 2
104 # define BOOST_TEST_CRT_ERROR 1
105 # define BOOST_TEST_CRT_SET_HOOK(H) (void*)(H)
108 # if (!BOOST_WORKAROUND(_MSC_VER, >= 1400 ) && \
109 !defined(BOOST_COMO)) || defined(UNDER_CE)
111 typedef void* _invalid_parameter_handler;
113 inline _invalid_parameter_handler
114 _set_invalid_parameter_handler( _invalid_parameter_handler arg )
121 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564)) || defined(UNDER_CE)
123 namespace { void _set_se_translator( void* ) {} }
127 #elif defined(BOOST_HAS_SIGACTION)
129 # define BOOST_SIGACTION_BASED_SIGNAL_HANDLING
135 # if defined(__FreeBSD__)
137 # include <osreldate.h>
140 # define SIGPOLL SIGIO
143 # if (__FreeBSD_version < 70100)
145 # define ILL_ILLADR 0 // ILL_RESAD_FAULT
146 # define ILL_PRVOPC ILL_PRIVIN_FAULT
147 # define ILL_ILLOPN 2 // ILL_RESOP_FAULT
148 # define ILL_COPROC ILL_FPOP_FAULT
150 # define BOOST_TEST_LIMITED_SIGNAL_DETAILS
155 # if defined(__ANDROID__)
156 # include <android/api-level.h>
159 // documentation of BOOST_TEST_DISABLE_ALT_STACK in execution_monitor.hpp
160 # if !defined(__CYGWIN__) && !defined(__QNXNTO__) && !defined(__bgq__) && \
161 (!defined(__ANDROID__) || __ANDROID_API__ >= 8) && \
162 !defined(BOOST_TEST_DISABLE_ALT_STACK)
163 # define BOOST_TEST_USE_ALT_STACK
166 # if defined(SIGPOLL) && !defined(__CYGWIN__) && \
167 !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) && \
168 !defined(__NetBSD__) && \
170 # define BOOST_TEST_CATCH_SIGPOLL
173 # ifdef BOOST_TEST_USE_ALT_STACK
174 # define BOOST_TEST_ALT_STACK_SIZE SIGSTKSZ
180 # define BOOST_NO_SIGNAL_HANDLING
188 #if !defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
189 # include <boost/core/demangle.hpp>
192 #include <boost/test/detail/suppress_warnings.hpp>
194 //____________________________________________________________________________//
198 // ************************************************************************** //
199 // ************** throw_exception ************** //
200 // ************************************************************************** //
202 #ifdef BOOST_NO_EXCEPTION
203 void throw_exception( std::exception const & e ) { abort(); }
206 // ************************************************************************** //
207 // ************** report_error ************** //
208 // ************************************************************************** //
213 # define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) std::vsnprintf( (a1), (a2), (a3), (a4) )
214 #elif BOOST_WORKAROUND(_MSC_VER, <= 1310) || \
215 BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3000)) || \
217 # define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) _vsnprintf( (a1), (a2), (a3), (a4) )
219 # define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) vsnprintf( (a1), (a2), (a3), (a4) )
222 #ifndef BOOST_NO_EXCEPTION
224 template <typename ErrorInfo>
225 typename ErrorInfo::value_type
226 extract( boost::exception const* ex )
231 typename ErrorInfo::value_type const * val = boost::get_error_info<ErrorInfo>( *ex );
233 return val ? *val : 0;
236 //____________________________________________________________________________//
239 report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, va_list* args )
241 static const int REPORT_ERROR_BUFFER_SIZE = 4096;
242 static char buf[REPORT_ERROR_BUFFER_SIZE];
244 BOOST_TEST_VSNPRINTF( buf, sizeof(buf)-1, format, *args );
245 buf[sizeof(buf)-1] = 0;
249 BOOST_TEST_I_THROW(execution_exception( ec, buf, execution_exception::location( extract<throw_file>( be ),
250 (size_t)extract<throw_line>( be ),
251 extract<throw_function>( be ) ) ));
254 //____________________________________________________________________________//
257 report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, ... )
260 va_start( args, format );
262 report_error( ec, be, format, &args );
267 //____________________________________________________________________________//
270 report_error( execution_exception::error_code ec, char const* format, ... )
273 va_start( args, format );
275 report_error( ec, 0, format, &args );
278 //____________________________________________________________________________//
280 template<typename Tr,typename Functor>
282 do_invoke( Tr const& tr, Functor const& F )
284 return tr ? (*tr)( F ) : F();
287 //____________________________________________________________________________//
289 struct fpe_except_guard {
290 explicit fpe_except_guard( unsigned detect_fpe )
291 : m_detect_fpe( detect_fpe )
293 // prepare fp exceptions control
294 m_previosly_enabled = fpe::disable( fpe::BOOST_FPE_ALL );
295 if( m_previosly_enabled != fpe::BOOST_FPE_INV && detect_fpe != fpe::BOOST_FPE_OFF )
296 fpe::enable( detect_fpe );
300 if( m_detect_fpe != fpe::BOOST_FPE_OFF )
301 fpe::disable( m_detect_fpe );
302 if( m_previosly_enabled != fpe::BOOST_FPE_INV )
303 fpe::enable( m_previosly_enabled );
306 unsigned m_detect_fpe;
307 unsigned m_previosly_enabled;
311 // ************************************************************************** //
312 // ************** typeid_name ************** //
313 // ************************************************************************** //
315 #if !defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
318 typeid_name( T const& t )
320 return boost::core::demangle(typeid(t).name());
324 } // namespace detail
326 #if defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING)
328 // ************************************************************************** //
329 // ************** Sigaction based signal handling ************** //
330 // ************************************************************************** //
334 // ************************************************************************** //
335 // ************** boost::detail::system_signal_exception ************** //
336 // ************************************************************************** //
338 class system_signal_exception {
341 system_signal_exception()
347 void operator()( siginfo_t* i, void* c )
356 siginfo_t* m_sig_info; // system signal detailed info
357 void* m_context; // signal context
360 //____________________________________________________________________________//
363 system_signal_exception::report() const
366 return; // no error actually occur?
368 switch( m_sig_info->si_code ) {
370 report_error( execution_exception::system_error,
371 "signal: generated by kill() (or family); uid=%d; pid=%d",
372 (int)m_sig_info->si_uid, (int)m_sig_info->si_pid );
375 report_error( execution_exception::system_error,
376 "signal: sent by sigqueue()" );
379 report_error( execution_exception::system_error,
380 "signal: the expiration of a timer set by timer_settimer()" );
383 report_error( execution_exception::system_error,
384 "signal: generated by the completion of an asynchronous I/O request" );
387 report_error( execution_exception::system_error,
388 "signal: generated by the the arrival of a message on an empty message queue" );
394 switch( m_sig_info->si_signo ) {
396 switch( m_sig_info->si_code ) {
397 #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
399 report_error( execution_exception::system_fatal_error,
400 "signal: illegal opcode; address of failing instruction: 0x%08lx",
401 m_sig_info->si_addr );
404 report_error( execution_exception::system_fatal_error,
405 "signal: illegal trap; address of failing instruction: 0x%08lx",
406 m_sig_info->si_addr );
409 report_error( execution_exception::system_fatal_error,
410 "signal: privileged register; address of failing instruction: 0x%08lx",
411 m_sig_info->si_addr );
414 report_error( execution_exception::system_fatal_error,
415 "signal: internal stack error; address of failing instruction: 0x%08lx",
416 m_sig_info->si_addr );
420 report_error( execution_exception::system_fatal_error,
421 "signal: illegal operand; address of failing instruction: 0x%08lx",
422 m_sig_info->si_addr );
425 report_error( execution_exception::system_fatal_error,
426 "signal: illegal addressing mode; address of failing instruction: 0x%08lx",
427 m_sig_info->si_addr );
430 report_error( execution_exception::system_fatal_error,
431 "signal: privileged opcode; address of failing instruction: 0x%08lx",
432 m_sig_info->si_addr );
435 report_error( execution_exception::system_fatal_error,
436 "signal: co-processor error; address of failing instruction: 0x%08lx",
437 m_sig_info->si_addr );
440 report_error( execution_exception::system_fatal_error,
441 "signal: SIGILL, si_code: %d (illegal instruction; address of failing instruction: 0x%08lx)",
442 m_sig_info->si_addr, m_sig_info->si_code );
448 switch( m_sig_info->si_code ) {
450 report_error( execution_exception::system_error,
451 "signal: integer divide by zero; address of failing instruction: 0x%08lx",
452 m_sig_info->si_addr );
455 report_error( execution_exception::system_error,
456 "signal: integer overflow; address of failing instruction: 0x%08lx",
457 m_sig_info->si_addr );
460 report_error( execution_exception::system_error,
461 "signal: floating point divide by zero; address of failing instruction: 0x%08lx",
462 m_sig_info->si_addr );
465 report_error( execution_exception::system_error,
466 "signal: floating point overflow; address of failing instruction: 0x%08lx",
467 m_sig_info->si_addr );
470 report_error( execution_exception::system_error,
471 "signal: floating point underflow; address of failing instruction: 0x%08lx",
472 m_sig_info->si_addr );
475 report_error( execution_exception::system_error,
476 "signal: floating point inexact result; address of failing instruction: 0x%08lx",
477 m_sig_info->si_addr );
480 report_error( execution_exception::system_error,
481 "signal: invalid floating point operation; address of failing instruction: 0x%08lx",
482 m_sig_info->si_addr );
485 report_error( execution_exception::system_error,
486 "signal: subscript out of range; address of failing instruction: 0x%08lx",
487 m_sig_info->si_addr );
490 report_error( execution_exception::system_error,
491 "signal: SIGFPE, si_code: %d (errnoneous arithmetic operations; address of failing instruction: 0x%08lx)",
492 m_sig_info->si_addr, m_sig_info->si_code );
498 switch( m_sig_info->si_code ) {
499 #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
501 report_error( execution_exception::system_fatal_error,
502 "memory access violation at address: 0x%08lx: no mapping at fault address",
503 m_sig_info->si_addr );
506 report_error( execution_exception::system_fatal_error,
507 "memory access violation at address: 0x%08lx: invalid permissions",
508 m_sig_info->si_addr );
512 report_error( execution_exception::system_fatal_error,
513 "signal: SIGSEGV, si_code: %d (memory access violation at address: 0x%08lx)",
514 m_sig_info->si_addr, m_sig_info->si_code );
520 switch( m_sig_info->si_code ) {
521 #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
523 report_error( execution_exception::system_fatal_error,
524 "memory access violation at address: 0x%08lx: invalid address alignment",
525 m_sig_info->si_addr );
528 report_error( execution_exception::system_fatal_error,
529 "memory access violation at address: 0x%08lx: non-existent physical address",
530 m_sig_info->si_addr );
533 report_error( execution_exception::system_fatal_error,
534 "memory access violation at address: 0x%08lx: object specific hardware error",
535 m_sig_info->si_addr );
539 report_error( execution_exception::system_fatal_error,
540 "signal: SIGSEGV, si_code: %d (memory access violation at address: 0x%08lx)",
541 m_sig_info->si_addr, m_sig_info->si_code );
546 #if defined(BOOST_TEST_CATCH_SIGPOLL)
549 switch( m_sig_info->si_code ) {
550 #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
552 report_error( execution_exception::system_error,
553 "data input available; band event %d",
554 (int)m_sig_info->si_band );
557 report_error( execution_exception::system_error,
558 "output buffers available; band event %d",
559 (int)m_sig_info->si_band );
562 report_error( execution_exception::system_error,
563 "input message available; band event %d",
564 (int)m_sig_info->si_band );
567 report_error( execution_exception::system_error,
568 "i/o error; band event %d",
569 (int)m_sig_info->si_band );
572 report_error( execution_exception::system_error,
573 "high priority input available; band event %d",
574 (int)m_sig_info->si_band );
576 #if defined(POLL_ERR) && defined(POLL_HUP) && (POLL_ERR - POLL_HUP)
578 report_error( execution_exception::system_error,
579 "device disconnected; band event %d",
580 (int)m_sig_info->si_band );
585 report_error( execution_exception::system_error,
586 "signal: SIGPOLL, si_code: %d (asynchronous I/O event occurred; band event %d)",
587 (int)m_sig_info->si_band, m_sig_info->si_code );
595 report_error( execution_exception::system_error,
596 "signal: SIGABRT (application abort requested)" );
600 report_error( execution_exception::timeout_error,
601 "signal: SIGALRM (timeout while executing function)" );
605 report_error( execution_exception::system_error,
606 "unrecognized signal %d", m_sig_info->si_signo );
610 //____________________________________________________________________________//
612 // ************************************************************************** //
613 // ************** boost::detail::signal_action ************** //
614 // ************************************************************************** //
616 // Forward declaration
618 static void boost_execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context );
619 static void boost_execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context );
622 class signal_action {
623 typedef struct sigaction* sigaction_ptr;
627 signal_action( int sig, bool install, bool attach_dbg, char* alt_stack );
634 struct sigaction m_new_action;
635 struct sigaction m_old_action;
638 //____________________________________________________________________________//
640 signal_action::signal_action()
641 : m_installed( false )
644 //____________________________________________________________________________//
646 signal_action::signal_action( int sig, bool install, bool attach_dbg, char* alt_stack )
648 , m_installed( install )
653 std::memset( &m_new_action, 0, sizeof(struct sigaction) );
655 BOOST_TEST_SYS_ASSERT( ::sigaction( m_sig , sigaction_ptr(), &m_new_action ) != -1 );
657 if( m_new_action.sa_sigaction || m_new_action.sa_handler ) {
662 m_new_action.sa_flags |= SA_SIGINFO;
663 m_new_action.sa_sigaction = attach_dbg ? &boost_execution_monitor_attaching_signal_handler
664 : &boost_execution_monitor_jumping_signal_handler;
665 BOOST_TEST_SYS_ASSERT( sigemptyset( &m_new_action.sa_mask ) != -1 );
667 #ifdef BOOST_TEST_USE_ALT_STACK
669 m_new_action.sa_flags |= SA_ONSTACK;
672 BOOST_TEST_SYS_ASSERT( ::sigaction( m_sig, &m_new_action, &m_old_action ) != -1 );
675 //____________________________________________________________________________//
677 signal_action::~signal_action()
680 ::sigaction( m_sig, &m_old_action , sigaction_ptr() );
683 //____________________________________________________________________________//
685 // ************************************************************************** //
686 // ************** boost::detail::signal_handler ************** //
687 // ************************************************************************** //
689 class signal_handler {
692 explicit signal_handler( bool catch_system_errors, bool detect_fpe, unsigned timeout, bool attach_dbg, char* alt_stack );
698 static sigjmp_buf& jump_buffer()
700 assert( !!s_active_handler );
702 return s_active_handler->m_sigjmp_buf;
705 static system_signal_exception& sys_sig()
707 assert( !!s_active_handler );
709 return s_active_handler->m_sys_sig;
714 signal_handler* m_prev_handler;
717 // Note: We intentionality do not catch SIGCHLD. Users have to deal with it themselves
718 signal_action m_ILL_action;
719 signal_action m_FPE_action;
720 signal_action m_SEGV_action;
721 signal_action m_BUS_action;
722 signal_action m_CHLD_action;
723 signal_action m_POLL_action;
724 signal_action m_ABRT_action;
725 signal_action m_ALRM_action;
727 sigjmp_buf m_sigjmp_buf;
728 system_signal_exception m_sys_sig;
730 static signal_handler* s_active_handler;
733 // !! need to be placed in thread specific storage
734 typedef signal_handler* signal_handler_ptr;
735 signal_handler* signal_handler::s_active_handler = signal_handler_ptr();
737 //____________________________________________________________________________//
739 signal_handler::signal_handler( bool catch_system_errors, bool detect_fpe, unsigned timeout, bool attach_dbg, char* alt_stack )
740 : m_prev_handler( s_active_handler )
741 , m_timeout( timeout )
742 , m_ILL_action ( SIGILL , catch_system_errors, attach_dbg, alt_stack )
743 , m_FPE_action ( SIGFPE , detect_fpe , attach_dbg, alt_stack )
744 , m_SEGV_action( SIGSEGV, catch_system_errors, attach_dbg, alt_stack )
745 , m_BUS_action ( SIGBUS , catch_system_errors, attach_dbg, alt_stack )
746 #ifdef BOOST_TEST_CATCH_SIGPOLL
747 , m_POLL_action( SIGPOLL, catch_system_errors, attach_dbg, alt_stack )
749 , m_ABRT_action( SIGABRT, catch_system_errors, attach_dbg, alt_stack )
750 , m_ALRM_action( SIGALRM, timeout > 0 , attach_dbg, alt_stack )
752 s_active_handler = this;
754 if( m_timeout > 0 ) {
759 #ifdef BOOST_TEST_USE_ALT_STACK
762 std::memset( &sigstk, 0, sizeof(stack_t) );
764 BOOST_TEST_SYS_ASSERT( ::sigaltstack( 0, &sigstk ) != -1 );
766 if( sigstk.ss_flags & SS_DISABLE ) {
767 sigstk.ss_sp = alt_stack;
768 sigstk.ss_size = BOOST_TEST_ALT_STACK_SIZE;
770 BOOST_TEST_SYS_ASSERT( ::sigaltstack( &sigstk, 0 ) != -1 );
776 //____________________________________________________________________________//
778 signal_handler::~signal_handler()
780 assert( s_active_handler == this );
785 #ifdef BOOST_TEST_USE_ALT_STACK
787 // We shouldn't need to explicitly initialize all the members here,
788 // but gcc warns if we don't, so add initializers for each of the
789 // members specified in the POSIX std:
790 stack_t sigstk = { 0, 0, 0 };
792 stack_t sigstk = { };
795 sigstk.ss_size = MINSIGSTKSZ;
796 sigstk.ss_flags = SS_DISABLE;
797 if( ::sigaltstack( &sigstk, 0 ) == -1 ) {
799 std::cerr << "******** errors disabling the alternate stack:" << std::endl
800 << "\t#error:" << error_n << std::endl
801 << "\t" << std::strerror( error_n ) << std::endl;
805 s_active_handler = m_prev_handler;
808 //____________________________________________________________________________//
810 // ************************************************************************** //
811 // ************** execution_monitor_signal_handler ************** //
812 // ************************************************************************** //
816 static void boost_execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context )
818 signal_handler::sys_sig()( info, context );
820 siglongjmp( signal_handler::jump_buffer(), sig );
823 //____________________________________________________________________________//
825 static void boost_execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context )
827 if( !debug::attach_debugger( false ) )
828 boost_execution_monitor_jumping_signal_handler( sig, info, context );
830 // debugger attached; it will handle the signal
831 BOOST_TEST_SYS_ASSERT( ::signal( sig, SIG_DFL ) != SIG_ERR );
834 //____________________________________________________________________________//
838 } // namespace detail
840 // ************************************************************************** //
841 // ************** execution_monitor::catch_signals ************** //
842 // ************************************************************************** //
845 execution_monitor::catch_signals( boost::function<int ()> const& F )
847 using namespace detail;
849 #if defined(__CYGWIN__)
850 p_catch_system_errors.value = false;
853 #ifdef BOOST_TEST_USE_ALT_STACK
854 if( !!p_use_alt_stack && !m_alt_stack )
855 m_alt_stack.reset( new char[BOOST_TEST_ALT_STACK_SIZE] );
857 p_use_alt_stack.value = false;
860 signal_handler local_signal_handler( p_catch_system_errors,
861 p_catch_system_errors || (p_detect_fp_exceptions != fpe::BOOST_FPE_OFF),
864 !p_use_alt_stack ? 0 : m_alt_stack.get() );
866 if( !sigsetjmp( signal_handler::jump_buffer(), 1 ) )
867 return detail::do_invoke( m_custom_translators , F );
869 BOOST_TEST_I_THROW( local_signal_handler.sys_sig() );
872 //____________________________________________________________________________//
874 #elif defined(BOOST_SEH_BASED_SIGNAL_HANDLING)
876 // ************************************************************************** //
877 // ************** Microsoft structured exception handling ************** //
878 // ************************************************************************** //
880 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
881 namespace { void _set_se_translator( void* ) {} }
886 // ************************************************************************** //
887 // ************** boost::detail::system_signal_exception ************** //
888 // ************************************************************************** //
890 class system_signal_exception {
893 explicit system_signal_exception( execution_monitor* em )
896 , m_fault_address( 0 )
901 int operator()( unsigned id, _EXCEPTION_POINTERS* exps );
905 execution_monitor* m_em;
908 void* m_fault_address;
912 //____________________________________________________________________________//
914 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
916 seh_catch_preventer( unsigned /* id */, _EXCEPTION_POINTERS* /* exps */ )
922 //____________________________________________________________________________//
925 system_signal_exception::operator()( unsigned id, _EXCEPTION_POINTERS* exps )
927 const unsigned MSFT_CPP_EXCEPT = 0xE06d7363; // EMSC
929 // C++ exception - allow to go through
930 if( id == MSFT_CPP_EXCEPT )
931 return EXCEPTION_CONTINUE_SEARCH;
933 // FPE detection is enabled, while system exception detection is not - check if this is actually FPE
934 if( !m_em->p_catch_system_errors ) {
935 if( !m_em->p_detect_fp_exceptions )
936 return EXCEPTION_CONTINUE_SEARCH;
939 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
940 case EXCEPTION_FLT_STACK_CHECK:
941 case EXCEPTION_FLT_DENORMAL_OPERAND:
942 case EXCEPTION_FLT_INEXACT_RESULT:
943 case EXCEPTION_FLT_OVERFLOW:
944 case EXCEPTION_FLT_UNDERFLOW:
945 case EXCEPTION_FLT_INVALID_OPERATION:
946 case STATUS_FLOAT_MULTIPLE_FAULTS:
947 case STATUS_FLOAT_MULTIPLE_TRAPS:
950 return EXCEPTION_CONTINUE_SEARCH;
954 if( !!m_em->p_auto_start_dbg && debug::attach_debugger( false ) ) {
955 m_em->p_catch_system_errors.value = false;
956 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
957 _set_se_translator( &seh_catch_preventer );
959 return EXCEPTION_CONTINUE_EXECUTION;
963 if( m_se_id == EXCEPTION_ACCESS_VIOLATION && exps->ExceptionRecord->NumberParameters == 2 ) {
964 m_fault_address = (void*)exps->ExceptionRecord->ExceptionInformation[1];
965 m_dir = exps->ExceptionRecord->ExceptionInformation[0] == 0;
968 return EXCEPTION_EXECUTE_HANDLER;
971 //____________________________________________________________________________//
974 system_signal_exception::report() const
977 // cases classified as system_fatal_error
978 case EXCEPTION_ACCESS_VIOLATION: {
979 if( !m_fault_address )
980 detail::report_error( execution_exception::system_fatal_error, "memory access violation" );
982 detail::report_error(
983 execution_exception::system_fatal_error,
984 "memory access violation occurred at address 0x%08lx, while attempting to %s",
986 m_dir ? " read inaccessible data"
987 : " write to an inaccessible (or protected) address"
992 case EXCEPTION_ILLEGAL_INSTRUCTION:
993 detail::report_error( execution_exception::system_fatal_error, "illegal instruction" );
996 case EXCEPTION_PRIV_INSTRUCTION:
997 detail::report_error( execution_exception::system_fatal_error, "tried to execute an instruction whose operation is not allowed in the current machine mode" );
1000 case EXCEPTION_IN_PAGE_ERROR:
1001 detail::report_error( execution_exception::system_fatal_error, "access to a memory page that is not present" );
1004 case EXCEPTION_STACK_OVERFLOW:
1005 detail::report_error( execution_exception::system_fatal_error, "stack overflow" );
1008 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
1009 detail::report_error( execution_exception::system_fatal_error, "tried to continue execution after a non continuable exception occurred" );
1012 // cases classified as (non-fatal) system_trap
1013 case EXCEPTION_DATATYPE_MISALIGNMENT:
1014 detail::report_error( execution_exception::system_error, "data misalignment" );
1017 case EXCEPTION_INT_DIVIDE_BY_ZERO:
1018 detail::report_error( execution_exception::system_error, "integer divide by zero" );
1021 case EXCEPTION_INT_OVERFLOW:
1022 detail::report_error( execution_exception::system_error, "integer overflow" );
1025 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1026 detail::report_error( execution_exception::system_error, "array bounds exceeded" );
1029 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
1030 detail::report_error( execution_exception::system_error, "floating point divide by zero" );
1033 case EXCEPTION_FLT_STACK_CHECK:
1034 detail::report_error( execution_exception::system_error,
1035 "stack overflowed or underflowed as the result of a floating-point operation" );
1038 case EXCEPTION_FLT_DENORMAL_OPERAND:
1039 detail::report_error( execution_exception::system_error,
1040 "operand of floating point operation is denormal" );
1043 case EXCEPTION_FLT_INEXACT_RESULT:
1044 detail::report_error( execution_exception::system_error,
1045 "result of a floating-point operation cannot be represented exactly" );
1048 case EXCEPTION_FLT_OVERFLOW:
1049 detail::report_error( execution_exception::system_error,
1050 "exponent of a floating-point operation is greater than the magnitude allowed by the corresponding type" );
1053 case EXCEPTION_FLT_UNDERFLOW:
1054 detail::report_error( execution_exception::system_error,
1055 "exponent of a floating-point operation is less than the magnitude allowed by the corresponding type" );
1058 case EXCEPTION_FLT_INVALID_OPERATION:
1059 detail::report_error( execution_exception::system_error, "floating point error" );
1062 case STATUS_FLOAT_MULTIPLE_FAULTS:
1063 detail::report_error( execution_exception::system_error, "multiple floating point errors" );
1066 case STATUS_FLOAT_MULTIPLE_TRAPS:
1067 detail::report_error( execution_exception::system_error, "multiple floating point errors" );
1070 case EXCEPTION_BREAKPOINT:
1071 detail::report_error( execution_exception::system_error, "breakpoint encountered" );
1075 detail::report_error( execution_exception::system_error, "unrecognized exception. Id: 0x%08lx", m_se_id );
1080 //____________________________________________________________________________//
1082 // ************************************************************************** //
1083 // ************** assert_reporting_function ************** //
1084 // ************************************************************************** //
1086 int BOOST_TEST_CALL_DECL
1087 assert_reporting_function( int reportType, char* userMessage, int* )
1089 // write this way instead of switch to avoid unreachable statements
1090 if( reportType == BOOST_TEST_CRT_ASSERT || reportType == BOOST_TEST_CRT_ERROR )
1091 detail::report_error( reportType == BOOST_TEST_CRT_ASSERT ? execution_exception::user_error : execution_exception::system_error, userMessage );
1094 } // assert_reporting_function
1096 //____________________________________________________________________________//
1098 void BOOST_TEST_CALL_DECL
1099 invalid_param_handler( wchar_t const* /* expr */,
1100 wchar_t const* /* func */,
1101 wchar_t const* /* file */,
1102 unsigned /* line */,
1103 uintptr_t /* reserved */)
1105 detail::report_error( execution_exception::user_error,
1106 "Invalid parameter detected by C runtime library" );
1109 //____________________________________________________________________________//
1111 } // namespace detail
1113 // ************************************************************************** //
1114 // ************** execution_monitor::catch_signals ************** //
1115 // ************************************************************************** //
1118 execution_monitor::catch_signals( boost::function<int ()> const& F )
1120 _invalid_parameter_handler old_iph = _invalid_parameter_handler();
1121 BOOST_TEST_CRT_HOOK_TYPE old_crt_hook = 0;
1123 if( p_catch_system_errors ) {
1124 old_crt_hook = BOOST_TEST_CRT_SET_HOOK( &detail::assert_reporting_function );
1126 old_iph = _set_invalid_parameter_handler(
1127 reinterpret_cast<_invalid_parameter_handler>( &detail::invalid_param_handler ) );
1128 } else if( !p_detect_fp_exceptions ) {
1129 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
1130 _set_se_translator( &detail::seh_catch_preventer );
1134 detail::system_signal_exception SSE( this );
1137 // clang windows workaround: this not available in __finally scope
1138 bool l_catch_system_errors = p_catch_system_errors;
1142 ret_val = detail::do_invoke( m_custom_translators, F );
1144 __except( SSE( GetExceptionCode(), GetExceptionInformation() ) ) {
1149 if( l_catch_system_errors ) {
1150 BOOST_TEST_CRT_SET_HOOK( old_crt_hook );
1152 _set_invalid_parameter_handler( old_iph );
1159 //____________________________________________________________________________//
1161 #else // default signal handler
1165 class system_signal_exception {
1167 void report() const {}
1170 } // namespace detail
1173 execution_monitor::catch_signals( boost::function<int ()> const& F )
1175 return detail::do_invoke( m_custom_translators , F );
1178 //____________________________________________________________________________//
1180 #endif // choose signal handler
1182 // ************************************************************************** //
1183 // ************** execution_monitor ************** //
1184 // ************************************************************************** //
1186 execution_monitor::execution_monitor()
1187 : p_catch_system_errors( true )
1188 , p_auto_start_dbg( false )
1190 , p_use_alt_stack( true )
1191 , p_detect_fp_exceptions( fpe::BOOST_FPE_OFF )
1194 //____________________________________________________________________________//
1197 execution_monitor::execute( boost::function<int ()> const& F )
1199 if( debug::under_debugger() )
1200 p_catch_system_errors.value = false;
1203 detail::fpe_except_guard G( p_detect_fp_exceptions );
1204 unit_test::ut_detail::ignore_unused_variable_warning( G );
1206 return catch_signals( F );
1209 #ifndef BOOST_NO_EXCEPTIONS
1211 // Catch-clause reference arguments are a bit different from function
1212 // arguments (ISO 15.3 paragraphs 18 & 19). Apparently const isn't
1213 // required. Programmers ask for const anyhow, so we supply it. That's
1214 // easier than answering questions about non-const usage.
1216 catch( char const* ex )
1217 { detail::report_error( execution_exception::cpp_exception_error,
1218 "C string: %s", ex ); }
1219 catch( std::string const& ex )
1220 { detail::report_error( execution_exception::cpp_exception_error,
1221 "std::string: %s", ex.c_str() ); }
1224 #if defined(BOOST_NO_TYPEID) || defined(BOOST_NO_RTTI)
1225 #define CATCH_AND_REPORT_STD_EXCEPTION( ex_name ) \
1226 catch( ex_name const& ex ) \
1227 { detail::report_error( execution_exception::cpp_exception_error, \
1228 current_exception_cast<boost::exception const>(), \
1229 #ex_name ": %s", ex.what() ); } \
1232 #define CATCH_AND_REPORT_STD_EXCEPTION( ex_name ) \
1233 catch( ex_name const& ex ) \
1234 { detail::report_error( execution_exception::cpp_exception_error, \
1235 current_exception_cast<boost::exception const>(), \
1236 "%s: %s", detail::typeid_name(ex).c_str(), ex.what() ); } \
1240 CATCH_AND_REPORT_STD_EXCEPTION( std::bad_alloc )
1242 #if BOOST_WORKAROUND(__BORLANDC__, <= 0x0551)
1243 CATCH_AND_REPORT_STD_EXCEPTION( std::bad_cast )
1244 CATCH_AND_REPORT_STD_EXCEPTION( std::bad_typeid )
1246 CATCH_AND_REPORT_STD_EXCEPTION( std::bad_cast )
1247 CATCH_AND_REPORT_STD_EXCEPTION( std::bad_typeid )
1250 CATCH_AND_REPORT_STD_EXCEPTION( std::bad_exception )
1251 CATCH_AND_REPORT_STD_EXCEPTION( std::domain_error )
1252 CATCH_AND_REPORT_STD_EXCEPTION( std::invalid_argument )
1253 CATCH_AND_REPORT_STD_EXCEPTION( std::length_error )
1254 CATCH_AND_REPORT_STD_EXCEPTION( std::out_of_range )
1255 CATCH_AND_REPORT_STD_EXCEPTION( std::range_error )
1256 CATCH_AND_REPORT_STD_EXCEPTION( std::overflow_error )
1257 CATCH_AND_REPORT_STD_EXCEPTION( std::underflow_error )
1258 CATCH_AND_REPORT_STD_EXCEPTION( std::logic_error )
1259 CATCH_AND_REPORT_STD_EXCEPTION( std::runtime_error )
1260 CATCH_AND_REPORT_STD_EXCEPTION( std::exception )
1261 #undef CATCH_AND_REPORT_STD_EXCEPTION
1263 catch( boost::exception const& ex )
1264 { detail::report_error( execution_exception::cpp_exception_error,
1266 #if defined(BOOST_NO_TYPEID) || defined(BOOST_NO_RTTI)
1267 "unknown boost::exception" ); }
1269 typeid(ex).name() ); }
1273 catch( system_error const& ex )
1274 { detail::report_error( execution_exception::cpp_exception_error,
1275 "system_error produced by: %s: %s", ex.p_failed_exp, std::strerror( ex.p_errno ) ); }
1276 catch( detail::system_signal_exception const& ex )
1280 catch( execution_aborted const& )
1284 catch( execution_exception const& )
1289 { detail::report_error( execution_exception::cpp_exception_error, "unknown type" ); }
1291 #endif // !BOOST_NO_EXCEPTION
1293 return 0; // never reached; supplied to quiet compiler warnings
1296 //____________________________________________________________________________//
1301 explicit forward( boost::function<void ()> const& F ) : m_F( F ) {}
1303 int operator()() { m_F(); return 0; }
1305 boost::function<void ()> const& m_F;
1308 } // namespace detail
1310 execution_monitor::vexecute( boost::function<void ()> const& F )
1312 execute( detail::forward( F ) );
1315 // ************************************************************************** //
1316 // ************** system_error ************** //
1317 // ************************************************************************** //
1319 system_error::system_error( char const* exp )
1321 : p_errno( GetLastError() )
1325 , p_failed_exp( exp )
1328 //____________________________________________________________________________//
1330 // ************************************************************************** //
1331 // ************** execution_exception ************** //
1332 // ************************************************************************** //
1334 execution_exception::execution_exception( error_code ec_, const_string what_msg_, location const& location_ )
1335 : m_error_code( ec_ )
1336 , m_what( what_msg_.empty() ? BOOST_TEST_L( "uncaught exception, system error or abort requested" ) : what_msg_ )
1337 , m_location( location_ )
1340 //____________________________________________________________________________//
1342 execution_exception::location::location( char const* file_name, size_t line_num, char const* func )
1343 : m_file_name( file_name ? file_name : "unknown location" )
1344 , m_line_num( line_num )
1345 , m_function( func )
1348 //____________________________________________________________________________//
1350 // ************************************************************************** //
1351 // **************Floating point exception management interface ************** //
1352 // ************************************************************************** //
1357 enable( unsigned mask )
1359 boost::ignore_unused(mask);
1361 #if defined(UNDER_CE)
1362 /* Not Implemented in Windows CE */
1364 #elif defined(BOOST_SEH_BASED_SIGNAL_HANDLING)
1367 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
1368 unsigned old_cw = ::_controlfp( 0, 0 );
1369 ::_controlfp( old_cw & ~mask, BOOST_FPE_ALL );
1372 if( ::_controlfp_s( &old_cw, 0, 0 ) != 0 )
1373 return BOOST_FPE_INV;
1375 // Set the control word
1376 if( ::_controlfp_s( 0, old_cw & ~mask, BOOST_FPE_ALL ) != 0 )
1377 return BOOST_FPE_INV;
1380 return ~old_cw & BOOST_FPE_ALL;
1381 #elif defined(__GLIBC__) && defined(__USE_GNU) && !defined(BOOST_CLANG) && !defined(BOOST_NO_FENV_H)
1382 feclearexcept(BOOST_FPE_ALL);
1383 int res = feenableexcept( mask );
1384 return res == -1 ? (unsigned)BOOST_FPE_INV : (unsigned)res;
1386 /* Not Implemented */
1391 //____________________________________________________________________________//
1394 disable( unsigned mask )
1396 boost::ignore_unused(mask);
1398 #if defined(UNDER_CE)
1399 /* Not Implemented in Windows CE */
1401 #elif defined(BOOST_SEH_BASED_SIGNAL_HANDLING)
1404 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
1405 unsigned old_cw = ::_controlfp( 0, 0 );
1406 ::_controlfp( old_cw | mask, BOOST_FPE_ALL );
1409 if( ::_controlfp_s( &old_cw, 0, 0 ) != 0 )
1410 return BOOST_FPE_INV;
1412 // Set the control word
1413 if( ::_controlfp_s( 0, old_cw | mask, BOOST_FPE_ALL ) != 0 )
1414 return BOOST_FPE_INV;
1417 return ~old_cw & BOOST_FPE_ALL;
1418 #elif defined(__GLIBC__) && defined(__USE_GNU) && !defined(BOOST_CLANG) && !defined(BOOST_NO_FENV_H)
1419 feclearexcept(BOOST_FPE_ALL);
1420 int res = fedisableexcept( mask );
1421 return res == -1 ? (unsigned)BOOST_FPE_INV : (unsigned)res;
1423 /* Not Implemented */
1424 return BOOST_FPE_INV;
1428 //____________________________________________________________________________//
1432 } // namespace boost
1434 #include <boost/test/detail/enable_warnings.hpp>
1436 #endif // BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER