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/throw_exception.hpp>
27 #include <boost/test/execution_monitor.hpp>
28 #include <boost/test/debug.hpp>
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>
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
51 #include <cstdarg> // for varargs
53 #include <cmath> // for ceil
55 #include <iostream> // for varargs
57 #ifdef BOOST_NO_STDC_NAMESPACE
58 namespace std { using ::strerror; using ::strlen; using ::strncat; using ::ceil; }
62 #if defined(__SUNPRO_CC) || defined(__SunOS) || defined(__QNXNTO__) || defined(__VXWORKS__)
66 #if defined(__VXWORKS__)
67 # define BOOST_TEST_LIMITED_SIGNAL_DETAILS
70 #ifdef BOOST_SEH_BASED_SIGNAL_HANDLING
72 # if !defined(_WIN32_WINNT) // WinXP
73 # define _WIN32_WINNT 0x0501
78 # if defined(__MWERKS__) || (defined(_MSC_VER) && !defined(UNDER_CE))
82 # if defined(__BORLANDC__) && __BORLANDC__ >= 0x560 || defined(__MWERKS__)
86 # if defined(__BORLANDC__) && __BORLANDC__ < 0x560
87 typedef unsigned uintptr_t;
90 # if defined(UNDER_CE) && BOOST_WORKAROUND(_MSC_VER, < 1500 )
91 typedef void* uintptr_t;
92 # elif defined(UNDER_CE)
96 # if !defined(NDEBUG) && defined(_MSC_VER) && !defined(UNDER_CE)
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)
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)
109 # if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) /* WinXP */
110 # define BOOST_TEST_WIN32_WAITABLE_TIMERS
113 # if (!BOOST_WORKAROUND(_MSC_VER, >= 1400 ) && \
114 !defined(BOOST_COMO)) || defined(UNDER_CE)
116 typedef void* _invalid_parameter_handler;
118 inline _invalid_parameter_handler
119 _set_invalid_parameter_handler( _invalid_parameter_handler arg )
126 # if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564)) || defined(UNDER_CE)
128 namespace { void _set_se_translator( void* ) {} }
132 #elif defined(BOOST_HAS_SIGACTION)
134 # define BOOST_SIGACTION_BASED_SIGNAL_HANDLING
140 # if defined(__FreeBSD__)
142 # include <osreldate.h>
145 # define SIGPOLL SIGIO
148 # if (__FreeBSD_version < 70100)
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
155 # define BOOST_TEST_LIMITED_SIGNAL_DETAILS
160 # if defined(__ANDROID__)
161 # include <android/api-level.h>
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) && \
167 !defined(BOOST_TEST_DISABLE_ALT_STACK)
168 # define BOOST_TEST_USE_ALT_STACK
171 # if defined(SIGPOLL) && !defined(__CYGWIN__) && \
172 !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) && \
173 !defined(__NetBSD__) && \
175 # define BOOST_TEST_CATCH_SIGPOLL
178 # ifdef BOOST_TEST_USE_ALT_STACK
179 # define BOOST_TEST_ALT_STACK_SIZE SIGSTKSZ
185 # define BOOST_NO_SIGNAL_HANDLING
193 #if !defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
194 # include <boost/core/demangle.hpp>
197 #include <boost/test/detail/suppress_warnings.hpp>
199 //____________________________________________________________________________//
203 // ************************************************************************** //
204 // ************** throw_exception ************** //
205 // ************************************************************************** //
207 #ifdef BOOST_NO_EXCEPTIONS
208 void throw_exception( std::exception const & e ) { abort(); }
211 // ************************************************************************** //
212 // ************** report_error ************** //
213 // ************************************************************************** //
218 # define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) std::vsnprintf( (a1), (a2), (a3), (a4) )
219 #elif BOOST_WORKAROUND(_MSC_VER, <= 1310) || \
220 BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3000)) || \
221 defined(UNDER_CE) || \
222 (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
223 # define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) _vsnprintf( (a1), (a2), (a3), (a4) )
225 # define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) vsnprintf( (a1), (a2), (a3), (a4) )
228 #ifndef BOOST_NO_EXCEPTIONS
230 template <typename ErrorInfo>
231 typename ErrorInfo::value_type
232 extract( boost::exception const* ex )
237 typename ErrorInfo::value_type const * val = boost::get_error_info<ErrorInfo>( *ex );
239 return val ? *val : 0;
242 //____________________________________________________________________________//
246 __attribute__((__format__ (__printf__, 3, 0)))
248 report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, va_list* args )
250 static const int REPORT_ERROR_BUFFER_SIZE = 4096;
251 static char buf[REPORT_ERROR_BUFFER_SIZE];
253 BOOST_TEST_VSNPRINTF( buf, sizeof(buf)-1, format, *args );
254 buf[sizeof(buf)-1] = 0;
258 BOOST_TEST_I_THROW(execution_exception( ec, buf, execution_exception::location( extract<throw_file>( be ),
259 (size_t)extract<throw_line>( be ),
260 extract<throw_function>( be ) ) ));
263 //____________________________________________________________________________//
267 __attribute__((__format__ (__printf__, 3, 4)))
269 report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, ... )
272 va_start( args, format );
274 report_error( ec, be, format, &args );
279 //____________________________________________________________________________//
283 __attribute__((__format__ (__printf__, 2, 3)))
285 report_error( execution_exception::error_code ec, char const* format, ... )
288 va_start( args, format );
290 report_error( ec, 0, format, &args );
293 //____________________________________________________________________________//
295 template<typename Tr,typename Functor>
297 do_invoke( Tr const& tr, Functor const& F )
299 return tr ? (*tr)( F ) : F();
302 //____________________________________________________________________________//
304 struct fpe_except_guard {
305 explicit fpe_except_guard( unsigned detect_fpe )
306 : m_detect_fpe( detect_fpe )
308 // prepare fp exceptions control
309 m_previously_enabled = fpe::disable( fpe::BOOST_FPE_ALL );
310 if( m_previously_enabled != fpe::BOOST_FPE_INV && detect_fpe != fpe::BOOST_FPE_OFF )
311 fpe::enable( detect_fpe );
315 if( m_detect_fpe != fpe::BOOST_FPE_OFF )
316 fpe::disable( m_detect_fpe );
317 if( m_previously_enabled != fpe::BOOST_FPE_INV )
318 fpe::enable( m_previously_enabled );
321 unsigned m_detect_fpe;
322 unsigned m_previously_enabled;
326 // ************************************************************************** //
327 // ************** typeid_name ************** //
328 // ************************************************************************** //
330 #if !defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
333 typeid_name( T const& t )
335 return boost::core::demangle(typeid(t).name());
339 } // namespace detail
341 #if defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING)
343 // ************************************************************************** //
344 // ************** Sigaction based signal handling ************** //
345 // ************************************************************************** //
349 // ************************************************************************** //
350 // ************** boost::detail::system_signal_exception ************** //
351 // ************************************************************************** //
353 class system_signal_exception {
356 system_signal_exception()
362 void operator()( siginfo_t* i, void* c )
371 siginfo_t* m_sig_info; // system signal detailed info
372 void* m_context; // signal context
375 //____________________________________________________________________________//
378 system_signal_exception::report() const
381 return; // no error actually occur?
383 switch( m_sig_info->si_code ) {
385 // a bit of a hack to adapt code to small m_sig_info VxWorks uses
386 #define si_addr si_value.sival_int
387 #define si_band si_value.sival_int
390 report_error( execution_exception::system_error,
391 "signal: generated by kill() (or family); uid=%d; pid=%d",
392 (int)m_sig_info->si_uid, (int)m_sig_info->si_pid );
396 report_error( execution_exception::system_error,
397 "signal: sent by sigqueue()" );
400 report_error( execution_exception::system_error,
401 "signal: the expiration of a timer set by timer_settimer()" );
403 // OpenBSD was missing SI_ASYNCIO and SI_MESGQ
406 report_error( execution_exception::system_error,
407 "signal: generated by the completion of an asynchronous I/O request" );
412 report_error( execution_exception::system_error,
413 "signal: generated by the the arrival of a message on an empty message queue" );
420 switch( m_sig_info->si_signo ) {
422 switch( m_sig_info->si_code ) {
423 #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
425 report_error( execution_exception::system_fatal_error,
426 "signal: illegal opcode; address of failing instruction: 0x%08lx",
427 (uintptr_t) m_sig_info->si_addr );
430 report_error( execution_exception::system_fatal_error,
431 "signal: illegal trap; address of failing instruction: 0x%08lx",
432 (uintptr_t) m_sig_info->si_addr );
435 report_error( execution_exception::system_fatal_error,
436 "signal: privileged register; address of failing instruction: 0x%08lx",
437 (uintptr_t) m_sig_info->si_addr );
440 report_error( execution_exception::system_fatal_error,
441 "signal: internal stack error; address of failing instruction: 0x%08lx",
442 (uintptr_t) m_sig_info->si_addr );
446 report_error( execution_exception::system_fatal_error,
447 "signal: illegal operand; address of failing instruction: 0x%08lx",
448 (uintptr_t) m_sig_info->si_addr );
451 report_error( execution_exception::system_fatal_error,
452 "signal: illegal addressing mode; address of failing instruction: 0x%08lx",
453 (uintptr_t) m_sig_info->si_addr );
456 report_error( execution_exception::system_fatal_error,
457 "signal: privileged opcode; address of failing instruction: 0x%08lx",
458 (uintptr_t) m_sig_info->si_addr );
461 report_error( execution_exception::system_fatal_error,
462 "signal: co-processor error; address of failing instruction: 0x%08lx",
463 (uintptr_t) m_sig_info->si_addr );
466 report_error( execution_exception::system_fatal_error,
467 "signal: SIGILL, si_code: %d (illegal instruction; address of failing instruction: 0x%08lx)",
468 m_sig_info->si_code, (uintptr_t) m_sig_info->si_addr );
474 switch( m_sig_info->si_code ) {
476 report_error( execution_exception::system_error,
477 "signal: integer divide by zero; address of failing instruction: 0x%08lx",
478 (uintptr_t) m_sig_info->si_addr );
481 report_error( execution_exception::system_error,
482 "signal: integer overflow; address of failing instruction: 0x%08lx",
483 (uintptr_t) m_sig_info->si_addr );
486 report_error( execution_exception::system_error,
487 "signal: floating point divide by zero; address of failing instruction: 0x%08lx",
488 (uintptr_t) m_sig_info->si_addr );
491 report_error( execution_exception::system_error,
492 "signal: floating point overflow; address of failing instruction: 0x%08lx",
493 (uintptr_t) m_sig_info->si_addr );
496 report_error( execution_exception::system_error,
497 "signal: floating point underflow; address of failing instruction: 0x%08lx",
498 (uintptr_t) m_sig_info->si_addr );
501 report_error( execution_exception::system_error,
502 "signal: floating point inexact result; address of failing instruction: 0x%08lx",
503 (uintptr_t) m_sig_info->si_addr );
506 report_error( execution_exception::system_error,
507 "signal: invalid floating point operation; address of failing instruction: 0x%08lx",
508 (uintptr_t) m_sig_info->si_addr );
511 report_error( execution_exception::system_error,
512 "signal: subscript out of range; address of failing instruction: 0x%08lx",
513 (uintptr_t) m_sig_info->si_addr );
516 report_error( execution_exception::system_error,
517 "signal: SIGFPE, si_code: %d (errnoneous arithmetic operations; address of failing instruction: 0x%08lx)",
518 m_sig_info->si_code, (uintptr_t) m_sig_info->si_addr );
524 switch( m_sig_info->si_code ) {
525 #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
527 report_error( execution_exception::system_fatal_error,
528 "memory access violation at address: 0x%08lx: no mapping at fault address",
529 (uintptr_t) m_sig_info->si_addr );
532 report_error( execution_exception::system_fatal_error,
533 "memory access violation at address: 0x%08lx: invalid permissions",
534 (uintptr_t) m_sig_info->si_addr );
538 report_error( execution_exception::system_fatal_error,
539 "signal: SIGSEGV, si_code: %d (memory access violation at address: 0x%08lx)",
540 m_sig_info->si_code, (uintptr_t) m_sig_info->si_addr );
546 switch( m_sig_info->si_code ) {
547 #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
549 report_error( execution_exception::system_fatal_error,
550 "memory access violation at address: 0x%08lx: invalid address alignment",
551 (uintptr_t) m_sig_info->si_addr );
554 report_error( execution_exception::system_fatal_error,
555 "memory access violation at address: 0x%08lx: non-existent physical address",
556 (uintptr_t) m_sig_info->si_addr );
559 report_error( execution_exception::system_fatal_error,
560 "memory access violation at address: 0x%08lx: object specific hardware error",
561 (uintptr_t) m_sig_info->si_addr );
565 report_error( execution_exception::system_fatal_error,
566 "signal: SIGSEGV, si_code: %d (memory access violation at address: 0x%08lx)",
567 m_sig_info->si_code, (uintptr_t) m_sig_info->si_addr );
572 #if defined(BOOST_TEST_CATCH_SIGPOLL)
575 switch( m_sig_info->si_code ) {
576 #ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
578 report_error( execution_exception::system_error,
579 "data input available; band event %d",
580 (int)m_sig_info->si_band );
583 report_error( execution_exception::system_error,
584 "output buffers available; band event %d",
585 (int)m_sig_info->si_band );
588 report_error( execution_exception::system_error,
589 "input message available; band event %d",
590 (int)m_sig_info->si_band );
593 report_error( execution_exception::system_error,
594 "i/o error; band event %d",
595 (int)m_sig_info->si_band );
598 report_error( execution_exception::system_error,
599 "high priority input available; band event %d",
600 (int)m_sig_info->si_band );
602 #if defined(POLL_ERR) && defined(POLL_HUP) && (POLL_ERR - POLL_HUP)
604 report_error( execution_exception::system_error,
605 "device disconnected; band event %d",
606 (int)m_sig_info->si_band );
611 report_error( execution_exception::system_error,
612 "signal: SIGPOLL, si_code: %d (asynchronous I/O event occurred; band event %d)",
613 m_sig_info->si_code, (int)m_sig_info->si_band );
621 report_error( execution_exception::system_error,
622 "signal: SIGABRT (application abort requested)" );
626 report_error( execution_exception::timeout_error,
627 "signal: SIGALRM (timeout while executing function)" );
631 report_error( execution_exception::system_error,
632 "unrecognized signal %d", m_sig_info->si_signo );
636 //____________________________________________________________________________//
638 // ************************************************************************** //
639 // ************** boost::detail::signal_action ************** //
640 // ************************************************************************** //
642 // Forward declaration
644 static void boost_execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context );
645 static void boost_execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context );
648 class signal_action {
649 typedef struct sigaction* sigaction_ptr;
653 signal_action( int sig, bool install, bool attach_dbg, char* alt_stack );
660 struct sigaction m_new_action;
661 struct sigaction m_old_action;
664 //____________________________________________________________________________//
666 signal_action::signal_action()
667 : m_installed( false )
670 //____________________________________________________________________________//
672 signal_action::signal_action( int sig, bool install, bool attach_dbg, char* alt_stack )
674 , m_installed( install )
679 std::memset( &m_new_action, 0, sizeof(struct sigaction) );
681 BOOST_TEST_SYS_ASSERT( ::sigaction( m_sig , sigaction_ptr(), &m_new_action ) != -1 );
683 if( m_new_action.sa_sigaction || m_new_action.sa_handler ) {
688 m_new_action.sa_flags |= SA_SIGINFO;
689 m_new_action.sa_sigaction = attach_dbg ? &boost_execution_monitor_attaching_signal_handler
690 : &boost_execution_monitor_jumping_signal_handler;
691 BOOST_TEST_SYS_ASSERT( sigemptyset( &m_new_action.sa_mask ) != -1 );
693 #ifdef BOOST_TEST_USE_ALT_STACK
695 m_new_action.sa_flags |= SA_ONSTACK;
698 BOOST_TEST_SYS_ASSERT( ::sigaction( m_sig, &m_new_action, &m_old_action ) != -1 );
701 //____________________________________________________________________________//
703 signal_action::~signal_action()
706 ::sigaction( m_sig, &m_old_action , sigaction_ptr() );
709 //____________________________________________________________________________//
711 // ************************************************************************** //
712 // ************** boost::detail::signal_handler ************** //
713 // ************************************************************************** //
715 class signal_handler {
718 explicit signal_handler( bool catch_system_errors, bool detect_fpe, unsigned timeout_microseconds, bool attach_dbg, char* alt_stack );
724 static sigjmp_buf& jump_buffer()
726 assert( !!s_active_handler );
728 return s_active_handler->m_sigjmp_buf;
731 static system_signal_exception& sys_sig()
733 assert( !!s_active_handler );
735 return s_active_handler->m_sys_sig;
740 signal_handler* m_prev_handler;
741 unsigned m_timeout_microseconds;
743 // Note: We intentionality do not catch SIGCHLD. Users have to deal with it themselves
744 signal_action m_ILL_action;
745 signal_action m_FPE_action;
746 signal_action m_SEGV_action;
747 signal_action m_BUS_action;
748 signal_action m_CHLD_action;
749 signal_action m_POLL_action;
750 signal_action m_ABRT_action;
751 signal_action m_ALRM_action;
753 sigjmp_buf m_sigjmp_buf;
754 system_signal_exception m_sys_sig;
756 static signal_handler* s_active_handler;
759 // !! need to be placed in thread specific storage
760 typedef signal_handler* signal_handler_ptr;
761 signal_handler* signal_handler::s_active_handler = signal_handler_ptr();
763 //____________________________________________________________________________//
765 signal_handler::signal_handler( bool catch_system_errors, bool detect_fpe, unsigned timeout_microseconds, bool attach_dbg, char* alt_stack )
766 : m_prev_handler( s_active_handler )
767 , m_timeout_microseconds( timeout_microseconds )
768 , m_ILL_action ( SIGILL , catch_system_errors, attach_dbg, alt_stack )
769 , m_FPE_action ( SIGFPE , detect_fpe , attach_dbg, alt_stack )
770 , m_SEGV_action( SIGSEGV, catch_system_errors, attach_dbg, alt_stack )
771 , m_BUS_action ( SIGBUS , catch_system_errors, attach_dbg, alt_stack )
772 #ifdef BOOST_TEST_CATCH_SIGPOLL
773 , m_POLL_action( SIGPOLL, catch_system_errors, attach_dbg, alt_stack )
775 , m_ABRT_action( SIGABRT, catch_system_errors, attach_dbg, alt_stack )
776 , m_ALRM_action( SIGALRM, timeout_microseconds > 0, attach_dbg, alt_stack )
778 s_active_handler = this;
780 if( m_timeout_microseconds > 0 ) {
782 ::alarm( static_cast<unsigned int>(std::ceil(timeout_microseconds / 1E6) )); // alarm has a precision to the seconds
785 #ifdef BOOST_TEST_USE_ALT_STACK
788 std::memset( &sigstk, 0, sizeof(stack_t) );
790 BOOST_TEST_SYS_ASSERT( ::sigaltstack( 0, &sigstk ) != -1 );
792 if( sigstk.ss_flags & SS_DISABLE ) {
793 sigstk.ss_sp = alt_stack;
794 sigstk.ss_size = BOOST_TEST_ALT_STACK_SIZE;
796 BOOST_TEST_SYS_ASSERT( ::sigaltstack( &sigstk, 0 ) != -1 );
802 //____________________________________________________________________________//
804 signal_handler::~signal_handler()
806 assert( s_active_handler == this );
808 if( m_timeout_microseconds > 0 )
811 #ifdef BOOST_TEST_USE_ALT_STACK
813 // We shouldn't need to explicitly initialize all the members here,
814 // but gcc warns if we don't, so add initializers for each of the
815 // members specified in the POSIX std:
816 stack_t sigstk = { 0, 0, 0 };
818 stack_t sigstk = { };
821 sigstk.ss_size = MINSIGSTKSZ;
822 sigstk.ss_flags = SS_DISABLE;
823 if( ::sigaltstack( &sigstk, 0 ) == -1 ) {
825 std::cerr << "******** errors disabling the alternate stack:" << std::endl
826 << "\t#error:" << error_n << std::endl
827 << "\t" << std::strerror( error_n ) << std::endl;
831 s_active_handler = m_prev_handler;
834 //____________________________________________________________________________//
836 // ************************************************************************** //
837 // ************** execution_monitor_signal_handler ************** //
838 // ************************************************************************** //
842 static void boost_execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context )
844 signal_handler::sys_sig()( info, context );
846 siglongjmp( signal_handler::jump_buffer(), sig );
849 //____________________________________________________________________________//
851 static void boost_execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context )
853 if( !debug::attach_debugger( false ) )
854 boost_execution_monitor_jumping_signal_handler( sig, info, context );
856 // debugger attached; it will handle the signal
857 BOOST_TEST_SYS_ASSERT( ::signal( sig, SIG_DFL ) != SIG_ERR );
860 //____________________________________________________________________________//
864 } // namespace detail
866 // ************************************************************************** //
867 // ************** execution_monitor::catch_signals ************** //
868 // ************************************************************************** //
871 execution_monitor::catch_signals( boost::function<int ()> const& F )
873 using namespace detail;
875 #if defined(__CYGWIN__)
876 p_catch_system_errors.value = false;
879 #ifdef BOOST_TEST_USE_ALT_STACK
880 if( !!p_use_alt_stack && !m_alt_stack )
881 m_alt_stack.reset( new char[BOOST_TEST_ALT_STACK_SIZE] );
883 p_use_alt_stack.value = false;
886 signal_handler local_signal_handler( p_catch_system_errors,
887 p_catch_system_errors || (p_detect_fp_exceptions != fpe::BOOST_FPE_OFF),
890 !p_use_alt_stack ? 0 : m_alt_stack.get() );
892 if( !sigsetjmp( signal_handler::jump_buffer(), 1 ) )
893 return detail::do_invoke( m_custom_translators , F );
895 BOOST_TEST_I_THROW( local_signal_handler.sys_sig() );
898 //____________________________________________________________________________//
900 #elif defined(BOOST_SEH_BASED_SIGNAL_HANDLING)
902 // ************************************************************************** //
903 // ************** Microsoft structured exception handling ************** //
904 // ************************************************************************** //
906 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0564))
907 namespace { void _set_se_translator( void* ) {} }
912 // ************************************************************************** //
913 // ************** boost::detail::system_signal_exception ************** //
914 // ************************************************************************** //
916 class system_signal_exception {
919 explicit system_signal_exception( execution_monitor* em )
922 , m_fault_address( 0 )
927 void set_timed_out();
929 int operator()( unsigned id, _EXCEPTION_POINTERS* exps );
933 execution_monitor* m_em;
936 void* m_fault_address;
941 //____________________________________________________________________________//
943 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
945 seh_catch_preventer( unsigned /* id */, _EXCEPTION_POINTERS* /* exps */ )
951 //____________________________________________________________________________//
954 system_signal_exception::set_timed_out()
959 //____________________________________________________________________________//
962 system_signal_exception::operator()( unsigned id, _EXCEPTION_POINTERS* exps )
964 const unsigned MSFT_CPP_EXCEPT = 0xE06d7363; // EMSC
966 // C++ exception - allow to go through
967 if( id == MSFT_CPP_EXCEPT )
968 return EXCEPTION_CONTINUE_SEARCH;
970 // FPE detection is enabled, while system exception detection is not - check if this is actually FPE
971 if( !m_em->p_catch_system_errors ) {
972 if( !m_em->p_detect_fp_exceptions )
973 return EXCEPTION_CONTINUE_SEARCH;
976 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
977 case EXCEPTION_FLT_STACK_CHECK:
978 case EXCEPTION_FLT_DENORMAL_OPERAND:
979 case EXCEPTION_FLT_INEXACT_RESULT:
980 case EXCEPTION_FLT_OVERFLOW:
981 case EXCEPTION_FLT_UNDERFLOW:
982 case EXCEPTION_FLT_INVALID_OPERATION:
983 case STATUS_FLOAT_MULTIPLE_FAULTS:
984 case STATUS_FLOAT_MULTIPLE_TRAPS:
987 return EXCEPTION_CONTINUE_SEARCH;
991 if( !!m_em->p_auto_start_dbg && debug::attach_debugger( false ) ) {
992 m_em->p_catch_system_errors.value = false;
993 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
994 _set_se_translator( &seh_catch_preventer );
996 return EXCEPTION_CONTINUE_EXECUTION;
1000 if( m_se_id == EXCEPTION_ACCESS_VIOLATION && exps->ExceptionRecord->NumberParameters == 2 ) {
1001 m_fault_address = (void*)exps->ExceptionRecord->ExceptionInformation[1];
1002 m_dir = exps->ExceptionRecord->ExceptionInformation[0] == 0;
1005 return EXCEPTION_EXECUTE_HANDLER;
1008 //____________________________________________________________________________//
1011 system_signal_exception::report() const
1014 // cases classified as system_fatal_error
1015 case EXCEPTION_ACCESS_VIOLATION: {
1016 if( !m_fault_address )
1017 detail::report_error( execution_exception::system_fatal_error, "memory access violation" );
1019 detail::report_error(
1020 execution_exception::system_fatal_error,
1021 "memory access violation occurred at address 0x%08lx, while attempting to %s",
1023 m_dir ? " read inaccessible data"
1024 : " write to an inaccessible (or protected) address"
1029 case EXCEPTION_ILLEGAL_INSTRUCTION:
1030 detail::report_error( execution_exception::system_fatal_error, "illegal instruction" );
1033 case EXCEPTION_PRIV_INSTRUCTION:
1034 detail::report_error( execution_exception::system_fatal_error, "tried to execute an instruction whose operation is not allowed in the current machine mode" );
1037 case EXCEPTION_IN_PAGE_ERROR:
1038 detail::report_error( execution_exception::system_fatal_error, "access to a memory page that is not present" );
1041 case EXCEPTION_STACK_OVERFLOW:
1042 detail::report_error( execution_exception::system_fatal_error, "stack overflow" );
1045 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
1046 detail::report_error( execution_exception::system_fatal_error, "tried to continue execution after a non continuable exception occurred" );
1049 // cases classified as (non-fatal) system_trap
1050 case EXCEPTION_DATATYPE_MISALIGNMENT:
1051 detail::report_error( execution_exception::system_error, "data misalignment" );
1054 case EXCEPTION_INT_DIVIDE_BY_ZERO:
1055 detail::report_error( execution_exception::system_error, "integer divide by zero" );
1058 case EXCEPTION_INT_OVERFLOW:
1059 detail::report_error( execution_exception::system_error, "integer overflow" );
1062 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1063 detail::report_error( execution_exception::system_error, "array bounds exceeded" );
1066 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
1067 detail::report_error( execution_exception::system_error, "floating point divide by zero" );
1070 case EXCEPTION_FLT_STACK_CHECK:
1071 detail::report_error( execution_exception::system_error,
1072 "stack overflowed or underflowed as the result of a floating-point operation" );
1075 case EXCEPTION_FLT_DENORMAL_OPERAND:
1076 detail::report_error( execution_exception::system_error,
1077 "operand of floating point operation is denormal" );
1080 case EXCEPTION_FLT_INEXACT_RESULT:
1081 detail::report_error( execution_exception::system_error,
1082 "result of a floating-point operation cannot be represented exactly" );
1085 case EXCEPTION_FLT_OVERFLOW:
1086 detail::report_error( execution_exception::system_error,
1087 "exponent of a floating-point operation is greater than the magnitude allowed by the corresponding type" );
1090 case EXCEPTION_FLT_UNDERFLOW:
1091 detail::report_error( execution_exception::system_error,
1092 "exponent of a floating-point operation is less than the magnitude allowed by the corresponding type" );
1095 case EXCEPTION_FLT_INVALID_OPERATION:
1096 detail::report_error( execution_exception::system_error, "floating point error" );
1099 case STATUS_FLOAT_MULTIPLE_FAULTS:
1100 detail::report_error( execution_exception::system_error, "multiple floating point errors" );
1103 case STATUS_FLOAT_MULTIPLE_TRAPS:
1104 detail::report_error( execution_exception::system_error, "multiple floating point errors" );
1107 case EXCEPTION_BREAKPOINT:
1108 detail::report_error( execution_exception::system_error, "breakpoint encountered" );
1113 detail::report_error(execution_exception::timeout_error, "timeout while executing function");
1116 detail::report_error( execution_exception::system_error, "unrecognized exception. Id: 0x%08lx", m_se_id );
1122 //____________________________________________________________________________//
1124 // ************************************************************************** //
1125 // ************** assert_reporting_function ************** //
1126 // ************************************************************************** //
1128 int BOOST_TEST_CALL_DECL
1129 assert_reporting_function( int reportType, char* userMessage, int* )
1131 // write this way instead of switch to avoid unreachable statements
1132 if( reportType == BOOST_TEST_CRT_ASSERT || reportType == BOOST_TEST_CRT_ERROR )
1133 detail::report_error( reportType == BOOST_TEST_CRT_ASSERT ? execution_exception::user_error : execution_exception::system_error, userMessage );
1136 } // assert_reporting_function
1138 //____________________________________________________________________________//
1140 void BOOST_TEST_CALL_DECL
1141 invalid_param_handler( wchar_t const* /* expr */,
1142 wchar_t const* /* func */,
1143 wchar_t const* /* file */,
1144 unsigned /* line */,
1145 uintptr_t /* reserved */)
1147 detail::report_error( execution_exception::user_error,
1148 "Invalid parameter detected by C runtime library" );
1151 //____________________________________________________________________________//
1153 } // namespace detail
1155 // ************************************************************************** //
1156 // ************** execution_monitor::catch_signals ************** //
1157 // ************************************************************************** //
1160 execution_monitor::catch_signals( boost::function<int ()> const& F )
1162 _invalid_parameter_handler old_iph = _invalid_parameter_handler();
1163 BOOST_TEST_CRT_HOOK_TYPE old_crt_hook = 0;
1165 if( p_catch_system_errors ) {
1166 old_crt_hook = BOOST_TEST_CRT_SET_HOOK( &detail::assert_reporting_function );
1168 old_iph = _set_invalid_parameter_handler(
1169 reinterpret_cast<_invalid_parameter_handler>( &detail::invalid_param_handler ) );
1170 } else if( !p_detect_fp_exceptions ) {
1171 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
1172 _set_se_translator( &detail::seh_catch_preventer );
1176 #if defined(BOOST_TEST_WIN32_WAITABLE_TIMERS)
1177 HANDLE htimer = INVALID_HANDLE_VALUE;
1178 BOOL bTimerSuccess = FALSE;
1181 htimer = ::CreateWaitableTimer(
1184 NULL); // naming the timer might create collisions
1186 if( htimer != INVALID_HANDLE_VALUE ) {
1187 LARGE_INTEGER liDueTime;
1188 liDueTime.QuadPart = - static_cast<LONGLONG>(p_timeout) * 10ll; // resolution of 100 ns
1190 bTimerSuccess = ::SetWaitableTimer(
1196 FALSE); // Do not restore a suspended system
1201 detail::system_signal_exception SSE( this );
1204 // clang windows workaround: this not available in __finally scope
1205 bool l_catch_system_errors = p_catch_system_errors;
1209 ret_val = detail::do_invoke( m_custom_translators, F );
1211 __except( SSE( GetExceptionCode(), GetExceptionInformation() ) ) {
1215 // we check for time outs: we do not have any signaling facility on Win32
1216 // however, we signal a timeout as a hard error as for the other operating systems
1217 // and throw the signal error handler
1218 if( bTimerSuccess && htimer != INVALID_HANDLE_VALUE) {
1219 if (::WaitForSingleObject(htimer, 0) == WAIT_OBJECT_0) {
1220 SSE.set_timed_out();
1228 #if defined(BOOST_TEST_WIN32_WAITABLE_TIMERS)
1229 if( htimer != INVALID_HANDLE_VALUE ) {
1230 ::CloseHandle(htimer);
1234 if( l_catch_system_errors ) {
1235 BOOST_TEST_CRT_SET_HOOK( old_crt_hook );
1237 _set_invalid_parameter_handler( old_iph );
1244 //____________________________________________________________________________//
1246 #else // default signal handler
1250 class system_signal_exception {
1252 void report() const {}
1255 } // namespace detail
1258 execution_monitor::catch_signals( boost::function<int ()> const& F )
1260 return detail::do_invoke( m_custom_translators , F );
1263 //____________________________________________________________________________//
1265 #endif // choose signal handler
1267 // ************************************************************************** //
1268 // ************** execution_monitor ************** //
1269 // ************************************************************************** //
1271 execution_monitor::execution_monitor()
1272 : p_catch_system_errors( true )
1273 , p_auto_start_dbg( false )
1275 , p_use_alt_stack( true )
1276 , p_detect_fp_exceptions( fpe::BOOST_FPE_OFF )
1279 //____________________________________________________________________________//
1282 execution_monitor::execute( boost::function<int ()> const& F )
1284 if( debug::under_debugger() )
1285 p_catch_system_errors.value = false;
1288 detail::fpe_except_guard G( p_detect_fp_exceptions );
1289 boost::ignore_unused( G );
1291 return catch_signals( F );
1294 #ifndef BOOST_NO_EXCEPTIONS
1296 // Catch-clause reference arguments are a bit different from function
1297 // arguments (ISO 15.3 paragraphs 18 & 19). Apparently const isn't
1298 // required. Programmers ask for const anyhow, so we supply it. That's
1299 // easier than answering questions about non-const usage.
1301 catch( char const* ex )
1302 { detail::report_error( execution_exception::cpp_exception_error,
1303 "C string: %s", ex ); }
1304 catch( std::string const& ex )
1305 { detail::report_error( execution_exception::cpp_exception_error,
1306 "std::string: %s", ex.c_str() ); }
1308 // boost::exception (before std::exception, with extended diagnostic)
1309 catch( boost::exception const& ex )
1310 { detail::report_error( execution_exception::cpp_exception_error,
1312 "%s", boost::diagnostic_information(ex).c_str() ); }
1315 #if defined(BOOST_NO_TYPEID) || defined(BOOST_NO_RTTI)
1316 #define CATCH_AND_REPORT_STD_EXCEPTION( ex_name ) \
1317 catch( ex_name const& ex ) \
1318 { detail::report_error( execution_exception::cpp_exception_error, \
1319 current_exception_cast<boost::exception const>(), \
1320 #ex_name ": %s", ex.what() ); } \
1323 #define CATCH_AND_REPORT_STD_EXCEPTION( ex_name ) \
1324 catch( ex_name const& ex ) \
1325 { detail::report_error( execution_exception::cpp_exception_error, \
1326 current_exception_cast<boost::exception const>(), \
1327 "%s: %s", detail::typeid_name(ex).c_str(), ex.what() ); } \
1331 CATCH_AND_REPORT_STD_EXCEPTION( std::bad_alloc )
1332 CATCH_AND_REPORT_STD_EXCEPTION( std::bad_cast )
1333 CATCH_AND_REPORT_STD_EXCEPTION( std::bad_typeid )
1334 CATCH_AND_REPORT_STD_EXCEPTION( std::bad_exception )
1335 CATCH_AND_REPORT_STD_EXCEPTION( std::domain_error )
1336 CATCH_AND_REPORT_STD_EXCEPTION( std::invalid_argument )
1337 CATCH_AND_REPORT_STD_EXCEPTION( std::length_error )
1338 CATCH_AND_REPORT_STD_EXCEPTION( std::out_of_range )
1339 CATCH_AND_REPORT_STD_EXCEPTION( std::range_error )
1340 CATCH_AND_REPORT_STD_EXCEPTION( std::overflow_error )
1341 CATCH_AND_REPORT_STD_EXCEPTION( std::underflow_error )
1342 CATCH_AND_REPORT_STD_EXCEPTION( std::logic_error )
1343 CATCH_AND_REPORT_STD_EXCEPTION( std::runtime_error )
1344 CATCH_AND_REPORT_STD_EXCEPTION( std::exception )
1345 #undef CATCH_AND_REPORT_STD_EXCEPTION
1348 catch( system_error const& ex )
1349 { detail::report_error( execution_exception::cpp_exception_error,
1350 "system_error produced by: %s: %s", ex.p_failed_exp, std::strerror( ex.p_errno ) ); }
1351 catch( detail::system_signal_exception const& ex )
1355 catch( execution_aborted const& )
1359 catch( execution_exception const& )
1364 { detail::report_error( execution_exception::cpp_exception_error, "unknown type" ); }
1366 #endif // !BOOST_NO_EXCEPTIONS
1368 return 0; // never reached; supplied to quiet compiler warnings
1371 //____________________________________________________________________________//
1376 explicit forward( boost::function<void ()> const& F ) : m_F( F ) {}
1378 int operator()() { m_F(); return 0; }
1380 boost::function<void ()> const& m_F;
1383 } // namespace detail
1385 execution_monitor::vexecute( boost::function<void ()> const& F )
1387 execute( detail::forward( F ) );
1390 // ************************************************************************** //
1391 // ************** system_error ************** //
1392 // ************************************************************************** //
1394 system_error::system_error( char const* exp )
1396 : p_errno( GetLastError() )
1400 , p_failed_exp( exp )
1403 //____________________________________________________________________________//
1405 // ************************************************************************** //
1406 // ************** execution_exception ************** //
1407 // ************************************************************************** //
1409 execution_exception::execution_exception( error_code ec_, const_string what_msg_, location const& location_ )
1410 : m_error_code( ec_ )
1411 , m_what( what_msg_.empty() ? BOOST_TEST_L( "uncaught exception, system error or abort requested" ) : what_msg_ )
1412 , m_location( location_ )
1415 //____________________________________________________________________________//
1417 execution_exception::location::location( char const* file_name, size_t line_num, char const* func )
1418 : m_file_name( file_name ? file_name : "unknown location" )
1419 , m_line_num( line_num )
1420 , m_function( func )
1423 execution_exception::location::location(const_string file_name, size_t line_num, char const* func )
1424 : m_file_name( file_name )
1425 , m_line_num( line_num )
1426 , m_function( func )
1429 //____________________________________________________________________________//
1431 // ************************************************************************** //
1432 // **************Floating point exception management interface ************** //
1433 // ************************************************************************** //
1438 enable( unsigned mask )
1440 boost::ignore_unused(mask);
1441 #if defined(BOOST_TEST_FPE_SUPPORT_WITH_SEH__)
1444 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
1445 unsigned old_cw = ::_controlfp( 0, 0 );
1446 ::_controlfp( old_cw & ~mask, BOOST_FPE_ALL );
1449 if( ::_controlfp_s( &old_cw, 0, 0 ) != 0 )
1450 return BOOST_FPE_INV;
1452 // Set the control word
1453 if( ::_controlfp_s( 0, old_cw & ~mask, BOOST_FPE_ALL ) != 0 )
1454 return BOOST_FPE_INV;
1456 return ~old_cw & BOOST_FPE_ALL;
1458 #elif defined(BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__)
1459 // same macro definition as in execution_monitor.hpp
1460 if (BOOST_FPE_ALL == BOOST_FPE_OFF)
1461 /* Not Implemented */
1462 return BOOST_FPE_OFF;
1463 feclearexcept(BOOST_FPE_ALL);
1464 int res = feenableexcept( mask );
1465 return res == -1 ? (unsigned)BOOST_FPE_INV : (unsigned)res;
1467 /* Not Implemented */
1468 return BOOST_FPE_OFF;
1472 //____________________________________________________________________________//
1475 disable( unsigned mask )
1477 boost::ignore_unused(mask);
1479 #if defined(BOOST_TEST_FPE_SUPPORT_WITH_SEH__)
1481 #if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
1482 unsigned old_cw = ::_controlfp( 0, 0 );
1483 ::_controlfp( old_cw | mask, BOOST_FPE_ALL );
1486 if( ::_controlfp_s( &old_cw, 0, 0 ) != 0 )
1487 return BOOST_FPE_INV;
1489 // Set the control word
1490 if( ::_controlfp_s( 0, old_cw | mask, BOOST_FPE_ALL ) != 0 )
1491 return BOOST_FPE_INV;
1493 return ~old_cw & BOOST_FPE_ALL;
1495 #elif defined(BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__)
1496 if (BOOST_FPE_ALL == BOOST_FPE_OFF)
1497 /* Not Implemented */
1498 return BOOST_FPE_INV;
1499 feclearexcept(BOOST_FPE_ALL);
1500 int res = fedisableexcept( mask );
1501 return res == -1 ? (unsigned)BOOST_FPE_INV : (unsigned)res;
1503 /* Not Implemented */
1504 return BOOST_FPE_INV;
1508 //____________________________________________________________________________//
1512 } // namespace boost
1514 #include <boost/test/detail/enable_warnings.hpp>
1516 #endif // BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER