• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1//  (C) Copyright Gennadiy Rozental 2001.
2//  (C) Copyright Beman Dawes and Ullrich Koethe 1995-2001.
3//  Use, modification, and distribution are subject to the
4//  Boost Software License, Version 1.0. (See accompanying file
5//  http://www.boost.org/LICENSE_1_0.txt)
6
7//  See http://www.boost.org/libs/test for the library home page.
8//
9///  @file
10///  Provides execution monitor implementation for all supported
11///  configurations, including Microsoft structured exception based, unix signals
12///  based and special workarounds for borland
13///
14///  Note that when testing requirements or user wishes preclude use of this
15///  file as a separate compilation unit, it may be included as a header file.
16///
17///  Header dependencies are deliberately restricted to reduce coupling to other
18///  boost libraries.
19// ***************************************************************************
20
21#ifndef BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER
22#define BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER
23
24// Boost.Test
25#include <boost/test/detail/config.hpp>
26#include <boost/test/detail/throw_exception.hpp>
27#include <boost/test/execution_monitor.hpp>
28#include <boost/test/debug.hpp>
29
30// Boost
31#include <boost/cstdlib.hpp>    // for exit codes
32#include <boost/config.hpp>     // for workarounds
33#include <boost/core/ignore_unused.hpp> // for ignore_unused
34#ifndef BOOST_NO_EXCEPTIONS
35#include <boost/exception/get_error_info.hpp> // for get_error_info
36#include <boost/exception/current_exception_cast.hpp> // for current_exception_cast
37#include <boost/exception/diagnostic_information.hpp>
38#endif
39
40// STL
41#include <string>               // for std::string
42#include <new>                  // for std::bad_alloc
43#include <typeinfo>             // for std::bad_cast, std::bad_typeid
44#include <exception>            // for std::exception, std::bad_exception
45#include <stdexcept>            // for std exception hierarchy
46#include <cstring>              // for C string API
47#include <cassert>              // for assert
48#include <cstddef>              // for NULL
49#include <cstdio>               // for vsnprintf
50#include <stdio.h>
51#include <cstdarg>              // for varargs
52#include <stdarg.h>
53#include <cmath>                // for ceil
54
55#include <iostream>              // for varargs
56
57#ifdef BOOST_NO_STDC_NAMESPACE
58namespace std { using ::strerror; using ::strlen; using ::strncat; using ::ceil; }
59#endif
60
61// to use vsnprintf
62#if defined(__SUNPRO_CC) || defined(__SunOS) || defined(__QNXNTO__) || defined(__VXWORKS__)
63using std::va_list;
64#endif
65
66#if defined(__VXWORKS__)
67# define BOOST_TEST_LIMITED_SIGNAL_DETAILS
68#endif
69
70#ifdef BOOST_SEH_BASED_SIGNAL_HANDLING
71
72# if !defined(_WIN32_WINNT) // WinXP
73#   define _WIN32_WINNT  0x0501
74# endif
75
76#  include <windows.h>
77
78#  if defined(__MWERKS__) || (defined(_MSC_VER) && !defined(UNDER_CE))
79#    include <eh.h>
80#  endif
81
82#  if defined(BOOST_BORLANDC) && BOOST_BORLANDC >= 0x560 || defined(__MWERKS__)
83#    include <stdint.h>
84#  endif
85
86#  if defined(BOOST_BORLANDC) && BOOST_BORLANDC < 0x560
87    typedef unsigned uintptr_t;
88#  endif
89
90#  if defined(UNDER_CE) && BOOST_WORKAROUND(_MSC_VER,  < 1500 )
91   typedef void* uintptr_t;
92#  elif defined(UNDER_CE)
93#  include <crtdefs.h>
94#  endif
95
96#  if !defined(NDEBUG) && defined(_MSC_VER) && !defined(UNDER_CE)
97#    include <crtdbg.h>
98#    define BOOST_TEST_CRT_HOOK_TYPE    _CRT_REPORT_HOOK
99#    define BOOST_TEST_CRT_ASSERT       _CRT_ASSERT
100#    define BOOST_TEST_CRT_ERROR        _CRT_ERROR
101#    define BOOST_TEST_CRT_SET_HOOK(H)  _CrtSetReportHook(H)
102#  else
103#    define BOOST_TEST_CRT_HOOK_TYPE    void*
104#    define BOOST_TEST_CRT_ASSERT       2
105#    define BOOST_TEST_CRT_ERROR        1
106#    define BOOST_TEST_CRT_SET_HOOK(H)  (void*)(H)
107#  endif
108
109#  if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) /* WinXP */
110#    define BOOST_TEST_WIN32_WAITABLE_TIMERS
111#  endif
112
113#  if (!BOOST_WORKAROUND(_MSC_VER,  >= 1400 ) && \
114      !defined(BOOST_COMO)) || defined(UNDER_CE)
115
116typedef void* _invalid_parameter_handler;
117
118inline _invalid_parameter_handler
119_set_invalid_parameter_handler( _invalid_parameter_handler arg )
120{
121    return arg;
122}
123
124#  endif
125
126#  if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0564)) || defined(UNDER_CE)
127
128namespace { void _set_se_translator( void* ) {} }
129
130#  endif
131
132#elif defined(BOOST_HAS_SIGACTION)
133
134#  define BOOST_SIGACTION_BASED_SIGNAL_HANDLING
135
136#  include <unistd.h>
137#  include <signal.h>
138#  include <setjmp.h>
139
140#  if defined(__FreeBSD__)
141
142#    include <osreldate.h>
143
144#    ifndef SIGPOLL
145#      define SIGPOLL SIGIO
146#    endif
147
148#    if (__FreeBSD_version < 70100)
149
150#      define ILL_ILLADR 0 // ILL_RESAD_FAULT
151#      define ILL_PRVOPC ILL_PRIVIN_FAULT
152#      define ILL_ILLOPN 2 // ILL_RESOP_FAULT
153#      define ILL_COPROC ILL_FPOP_FAULT
154
155#      define BOOST_TEST_LIMITED_SIGNAL_DETAILS
156
157#    endif
158#  endif
159
160#  if defined(__ANDROID__)
161#    include <android/api-level.h>
162#  endif
163
164// documentation of BOOST_TEST_DISABLE_ALT_STACK in execution_monitor.hpp
165#  if !defined(__CYGWIN__) && !defined(__QNXNTO__) && !defined(__bgq__) && \
166   (!defined(__ANDROID__) || __ANDROID_API__ >= 8) && \
167   !defined(BOOST_TEST_DISABLE_ALT_STACK)
168#    define BOOST_TEST_USE_ALT_STACK
169#  endif
170
171#  if defined(SIGPOLL) && !defined(__CYGWIN__)                              && \
172      !(defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__))  && \
173      !defined(__NetBSD__)                                                  && \
174      !defined(__QNXNTO__)
175#    define BOOST_TEST_CATCH_SIGPOLL
176#  endif
177
178#  ifdef BOOST_TEST_USE_ALT_STACK
179#    define BOOST_TEST_ALT_STACK_SIZE SIGSTKSZ
180#  endif
181
182
183#else
184
185#  define BOOST_NO_SIGNAL_HANDLING
186
187#endif
188
189#ifndef UNDER_CE
190#include <errno.h>
191#endif
192
193#if !defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
194#  include <boost/core/demangle.hpp>
195#endif
196
197#include <boost/test/detail/suppress_warnings.hpp>
198
199//____________________________________________________________________________//
200
201namespace boost {
202
203// ************************************************************************** //
204// **************                 throw_exception              ************** //
205// ************************************************************************** //
206
207#ifdef BOOST_NO_EXCEPTIONS
208void throw_exception( std::exception const & e ) { abort(); }
209#endif
210
211// ************************************************************************** //
212// **************                  report_error                ************** //
213// ************************************************************************** //
214
215namespace detail {
216
217#ifdef BOOST_BORLANDC
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) )
224#else
225#  define BOOST_TEST_VSNPRINTF( a1, a2, a3, a4 ) vsnprintf( (a1), (a2), (a3), (a4) )
226#endif
227
228
229/* checks the printf formatting by adding a decorator to the function */
230#if __GNUC__ >= 3 || defined(BOOST_EMBTC)
231#define BOOST_TEST_PRINTF_ATTRIBUTE_CHECK(x, y) __attribute__((__format__ (__printf__, x, y)))
232#else
233#define BOOST_TEST_PRINTF_ATTRIBUTE_CHECK(x, y)
234#endif
235
236#ifndef BOOST_NO_EXCEPTIONS
237
238template <typename ErrorInfo>
239typename ErrorInfo::value_type
240extract( boost::exception const* ex )
241{
242    if( !ex )
243        return 0;
244
245    typename ErrorInfo::value_type const * val = boost::get_error_info<ErrorInfo>( *ex );
246
247    return val ? *val : 0;
248}
249
250//____________________________________________________________________________//
251
252static void
253BOOST_TEST_PRINTF_ATTRIBUTE_CHECK(3, 0)
254report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, va_list* args )
255{
256    static const int REPORT_ERROR_BUFFER_SIZE = 4096;
257    static char buf[REPORT_ERROR_BUFFER_SIZE];
258
259    BOOST_TEST_VSNPRINTF( buf, sizeof(buf)-1, format, *args );
260    buf[sizeof(buf)-1] = 0;
261
262    va_end( *args );
263
264    BOOST_TEST_I_THROW(execution_exception( ec, buf, execution_exception::location( extract<throw_file>( be ),
265                                                                                    (size_t)extract<throw_line>( be ),
266                                                                                    extract<throw_function>( be ) ) ));
267}
268
269//____________________________________________________________________________//
270
271static void
272BOOST_TEST_PRINTF_ATTRIBUTE_CHECK(3, 4)
273report_error( execution_exception::error_code ec, boost::exception const* be, char const* format, ... )
274{
275    va_list args;
276    va_start( args, format );
277
278    report_error( ec, be, format, &args );
279}
280
281#endif
282
283//____________________________________________________________________________//
284
285static void
286BOOST_TEST_PRINTF_ATTRIBUTE_CHECK(2, 3)
287report_error( execution_exception::error_code ec, char const* format, ... )
288{
289    va_list args;
290    va_start( args, format );
291
292    report_error( ec, 0, format, &args );
293}
294
295//____________________________________________________________________________//
296
297template<typename Tr,typename Functor>
298inline int
299do_invoke( Tr const& tr, Functor const& F )
300{
301    return tr ? (*tr)( F ) : F();
302}
303
304//____________________________________________________________________________//
305
306struct fpe_except_guard {
307    explicit fpe_except_guard( unsigned detect_fpe )
308    : m_detect_fpe( detect_fpe )
309    {
310        // prepare fp exceptions control
311        m_previously_enabled = fpe::disable( fpe::BOOST_FPE_ALL );
312        if( m_previously_enabled != fpe::BOOST_FPE_INV && detect_fpe != fpe::BOOST_FPE_OFF )
313            fpe::enable( detect_fpe );
314    }
315    ~fpe_except_guard()
316    {
317        if( m_detect_fpe != fpe::BOOST_FPE_OFF )
318            fpe::disable( m_detect_fpe );
319        if( m_previously_enabled != fpe::BOOST_FPE_INV )
320            fpe::enable( m_previously_enabled );
321    }
322
323    unsigned m_detect_fpe;
324    unsigned m_previously_enabled;
325};
326
327
328// ************************************************************************** //
329// **************                  typeid_name                 ************** //
330// ************************************************************************** //
331
332#if !defined(BOOST_NO_TYPEID) && !defined(BOOST_NO_RTTI)
333template<typename T>
334std::string
335typeid_name( T const& t )
336{
337    return boost::core::demangle(typeid(t).name());
338}
339#endif
340
341} // namespace detail
342
343#if defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING)
344
345// ************************************************************************** //
346// **************       Sigaction based signal handling        ************** //
347// ************************************************************************** //
348
349namespace detail {
350
351// ************************************************************************** //
352// **************    boost::detail::system_signal_exception    ************** //
353// ************************************************************************** //
354
355class system_signal_exception {
356public:
357    // Constructor
358    system_signal_exception()
359    : m_sig_info( 0 )
360    , m_context( 0 )
361    {}
362
363    // Access methods
364    void        operator()( siginfo_t* i, void* c )
365    {
366        m_sig_info  = i;
367        m_context   = c;
368    }
369    void        report() const;
370
371private:
372    // Data members
373    siginfo_t*  m_sig_info; // system signal detailed info
374    void*       m_context;  // signal context
375};
376
377//____________________________________________________________________________//
378
379void
380system_signal_exception::report() const
381{
382    if( !m_sig_info )
383        return; // no error actually occur?
384
385    switch( m_sig_info->si_code ) {
386#ifdef __VXWORKS__
387// a bit of a hack to adapt code to small m_sig_info VxWorks uses
388#define si_addr si_value.sival_int
389#define si_band si_value.sival_int
390#else
391    case SI_USER:
392        report_error( execution_exception::system_error,
393                      "signal: generated by kill() (or family); uid=%d; pid=%d",
394                      (int)m_sig_info->si_uid, (int)m_sig_info->si_pid );
395        break;
396#endif
397    case SI_QUEUE:
398        report_error( execution_exception::system_error,
399                      "signal: sent by sigqueue()" );
400        break;
401    case SI_TIMER:
402        report_error( execution_exception::system_error,
403                      "signal: the expiration of a timer set by timer_settimer()" );
404        break;
405// OpenBSD was missing SI_ASYNCIO and SI_MESGQ
406#ifdef SI_ASYNCIO
407    case SI_ASYNCIO:
408        report_error( execution_exception::system_error,
409                      "signal: generated by the completion of an asynchronous I/O request" );
410        break;
411#endif
412#ifdef SI_MESGQ
413    case SI_MESGQ:
414        report_error( execution_exception::system_error,
415                      "signal: generated by the the arrival of a message on an empty message queue" );
416        break;
417#endif
418    default:
419        break;
420    }
421
422    switch( m_sig_info->si_signo ) {
423    case SIGILL:
424        switch( m_sig_info->si_code ) {
425#ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
426        case ILL_ILLOPC:
427            report_error( execution_exception::system_fatal_error,
428                          "signal: illegal opcode; address of failing instruction: 0x%08lx",
429                          (uintptr_t) m_sig_info->si_addr );
430            break;
431        case ILL_ILLTRP:
432            report_error( execution_exception::system_fatal_error,
433                          "signal: illegal trap; address of failing instruction: 0x%08lx",
434                          (uintptr_t) m_sig_info->si_addr );
435            break;
436        case ILL_PRVREG:
437            report_error( execution_exception::system_fatal_error,
438                          "signal: privileged register; address of failing instruction: 0x%08lx",
439                          (uintptr_t) m_sig_info->si_addr );
440            break;
441        case ILL_BADSTK:
442            report_error( execution_exception::system_fatal_error,
443                          "signal: internal stack error; address of failing instruction: 0x%08lx",
444                          (uintptr_t) m_sig_info->si_addr );
445            break;
446#endif
447        case ILL_ILLOPN:
448            report_error( execution_exception::system_fatal_error,
449                          "signal: illegal operand; address of failing instruction: 0x%08lx",
450                          (uintptr_t) m_sig_info->si_addr );
451            break;
452        case ILL_ILLADR:
453            report_error( execution_exception::system_fatal_error,
454                          "signal: illegal addressing mode; address of failing instruction: 0x%08lx",
455                          (uintptr_t) m_sig_info->si_addr );
456            break;
457        case ILL_PRVOPC:
458            report_error( execution_exception::system_fatal_error,
459                          "signal: privileged opcode; address of failing instruction: 0x%08lx",
460                          (uintptr_t) m_sig_info->si_addr );
461            break;
462        case ILL_COPROC:
463            report_error( execution_exception::system_fatal_error,
464                          "signal: co-processor error; address of failing instruction: 0x%08lx",
465                          (uintptr_t) m_sig_info->si_addr );
466            break;
467        default:
468            report_error( execution_exception::system_fatal_error,
469                          "signal: SIGILL, si_code: %d (illegal instruction; address of failing instruction: 0x%08lx)",
470                          m_sig_info->si_code, (uintptr_t) m_sig_info->si_addr );
471            break;
472        }
473        break;
474
475    case SIGFPE:
476        switch( m_sig_info->si_code ) {
477        case FPE_INTDIV:
478            report_error( execution_exception::system_error,
479                          "signal: integer divide by zero; address of failing instruction: 0x%08lx",
480                          (uintptr_t) m_sig_info->si_addr );
481            break;
482        case FPE_INTOVF:
483            report_error( execution_exception::system_error,
484                          "signal: integer overflow; address of failing instruction: 0x%08lx",
485                          (uintptr_t) m_sig_info->si_addr );
486            break;
487        case FPE_FLTDIV:
488            report_error( execution_exception::system_error,
489                          "signal: floating point divide by zero; address of failing instruction: 0x%08lx",
490                          (uintptr_t) m_sig_info->si_addr );
491            break;
492        case FPE_FLTOVF:
493            report_error( execution_exception::system_error,
494                          "signal: floating point overflow; address of failing instruction: 0x%08lx",
495                          (uintptr_t) m_sig_info->si_addr );
496            break;
497        case FPE_FLTUND:
498            report_error( execution_exception::system_error,
499                          "signal: floating point underflow; address of failing instruction: 0x%08lx",
500                          (uintptr_t) m_sig_info->si_addr );
501            break;
502        case FPE_FLTRES:
503            report_error( execution_exception::system_error,
504                          "signal: floating point inexact result; address of failing instruction: 0x%08lx",
505                          (uintptr_t) m_sig_info->si_addr );
506            break;
507        case FPE_FLTINV:
508            report_error( execution_exception::system_error,
509                          "signal: invalid floating point operation; address of failing instruction: 0x%08lx",
510                          (uintptr_t) m_sig_info->si_addr );
511            break;
512        case FPE_FLTSUB:
513            report_error( execution_exception::system_error,
514                          "signal: subscript out of range; address of failing instruction: 0x%08lx",
515                          (uintptr_t) m_sig_info->si_addr );
516            break;
517        default:
518            report_error( execution_exception::system_error,
519                          "signal: SIGFPE, si_code: %d (errnoneous arithmetic operations; address of failing instruction: 0x%08lx)",
520                          m_sig_info->si_code, (uintptr_t) m_sig_info->si_addr );
521            break;
522        }
523        break;
524
525    case SIGSEGV:
526        switch( m_sig_info->si_code ) {
527#ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
528        case SEGV_MAPERR:
529            report_error( execution_exception::system_fatal_error,
530                          "memory access violation at address: 0x%08lx: no mapping at fault address",
531                          (uintptr_t) m_sig_info->si_addr );
532            break;
533        case SEGV_ACCERR:
534            report_error( execution_exception::system_fatal_error,
535                          "memory access violation at address: 0x%08lx: invalid permissions",
536                          (uintptr_t) m_sig_info->si_addr );
537            break;
538#endif
539        default:
540            report_error( execution_exception::system_fatal_error,
541                          "signal: SIGSEGV, si_code: %d (memory access violation at address: 0x%08lx)",
542                          m_sig_info->si_code, (uintptr_t) m_sig_info->si_addr );
543            break;
544        }
545        break;
546
547    case SIGBUS:
548        switch( m_sig_info->si_code ) {
549#ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
550        case BUS_ADRALN:
551            report_error( execution_exception::system_fatal_error,
552                          "memory access violation at address: 0x%08lx: invalid address alignment",
553                          (uintptr_t) m_sig_info->si_addr );
554            break;
555        case BUS_ADRERR:
556            report_error( execution_exception::system_fatal_error,
557                          "memory access violation at address: 0x%08lx: non-existent physical address",
558                          (uintptr_t) m_sig_info->si_addr );
559            break;
560        case BUS_OBJERR:
561            report_error( execution_exception::system_fatal_error,
562                          "memory access violation at address: 0x%08lx: object specific hardware error",
563                          (uintptr_t) m_sig_info->si_addr );
564            break;
565#endif
566        default:
567            report_error( execution_exception::system_fatal_error,
568                          "signal: SIGSEGV, si_code: %d (memory access violation at address: 0x%08lx)",
569                          m_sig_info->si_code, (uintptr_t) m_sig_info->si_addr );
570            break;
571        }
572        break;
573
574#if defined(BOOST_TEST_CATCH_SIGPOLL)
575
576    case SIGPOLL:
577        switch( m_sig_info->si_code ) {
578#ifndef BOOST_TEST_LIMITED_SIGNAL_DETAILS
579        case POLL_IN:
580            report_error( execution_exception::system_error,
581                          "data input available; band event %d",
582                          (int)m_sig_info->si_band );
583            break;
584        case POLL_OUT:
585            report_error( execution_exception::system_error,
586                          "output buffers available; band event %d",
587                          (int)m_sig_info->si_band );
588            break;
589        case POLL_MSG:
590            report_error( execution_exception::system_error,
591                          "input message available; band event %d",
592                          (int)m_sig_info->si_band );
593            break;
594        case POLL_ERR:
595            report_error( execution_exception::system_error,
596                          "i/o error; band event %d",
597                          (int)m_sig_info->si_band );
598            break;
599        case POLL_PRI:
600            report_error( execution_exception::system_error,
601                          "high priority input available; band event %d",
602                          (int)m_sig_info->si_band );
603            break;
604#if defined(POLL_ERR) && defined(POLL_HUP) && (POLL_ERR - POLL_HUP)
605        case POLL_HUP:
606            report_error( execution_exception::system_error,
607                          "device disconnected; band event %d",
608                          (int)m_sig_info->si_band );
609            break;
610#endif
611#endif
612        default:
613            report_error( execution_exception::system_error,
614                          "signal: SIGPOLL, si_code: %d (asynchronous I/O event occurred; band event %d)",
615                          m_sig_info->si_code, (int)m_sig_info->si_band );
616            break;
617        }
618        break;
619
620#endif
621
622    case SIGABRT:
623        report_error( execution_exception::system_error,
624                      "signal: SIGABRT (application abort requested)" );
625        break;
626
627    case SIGALRM:
628        report_error( execution_exception::timeout_error,
629                      "signal: SIGALRM (timeout while executing function)" );
630        break;
631
632    default:
633        report_error( execution_exception::system_error,
634                      "unrecognized signal %d", m_sig_info->si_signo );
635    }
636}
637
638//____________________________________________________________________________//
639
640// ************************************************************************** //
641// **************         boost::detail::signal_action         ************** //
642// ************************************************************************** //
643
644// Forward declaration
645extern "C" {
646static void boost_execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context );
647static void boost_execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context );
648}
649
650class signal_action {
651    typedef struct sigaction* sigaction_ptr;
652public:
653    //Constructor
654    signal_action();
655    signal_action( int sig, bool install, bool attach_dbg, char* alt_stack );
656    ~signal_action();
657
658private:
659    // Data members
660    int                 m_sig;
661    bool                m_installed;
662    struct sigaction    m_new_action;
663    struct sigaction    m_old_action;
664};
665
666//____________________________________________________________________________//
667
668signal_action::signal_action()
669: m_installed( false )
670{}
671
672//____________________________________________________________________________//
673
674signal_action::signal_action( int sig, bool install, bool attach_dbg, char* alt_stack )
675: m_sig( sig )
676, m_installed( install )
677{
678    if( !install )
679        return;
680
681    std::memset( &m_new_action, 0, sizeof(struct sigaction) );
682
683    BOOST_TEST_SYS_ASSERT( ::sigaction( m_sig , sigaction_ptr(), &m_new_action ) != -1 );
684
685    if( m_new_action.sa_sigaction || m_new_action.sa_handler ) {
686        m_installed = false;
687        return;
688    }
689
690    m_new_action.sa_flags     |= SA_SIGINFO;
691    m_new_action.sa_sigaction  = attach_dbg ? &boost_execution_monitor_attaching_signal_handler
692                                            : &boost_execution_monitor_jumping_signal_handler;
693    BOOST_TEST_SYS_ASSERT( sigemptyset( &m_new_action.sa_mask ) != -1 );
694
695#ifdef BOOST_TEST_USE_ALT_STACK
696    if( alt_stack )
697        m_new_action.sa_flags |= SA_ONSTACK;
698#endif
699
700    BOOST_TEST_SYS_ASSERT( ::sigaction( m_sig, &m_new_action, &m_old_action ) != -1 );
701}
702
703//____________________________________________________________________________//
704
705signal_action::~signal_action()
706{
707    if( m_installed )
708        ::sigaction( m_sig, &m_old_action , sigaction_ptr() );
709}
710
711//____________________________________________________________________________//
712
713// ************************************************************************** //
714// **************        boost::detail::signal_handler         ************** //
715// ************************************************************************** //
716
717class signal_handler {
718public:
719    // Constructor
720    explicit signal_handler( bool catch_system_errors,
721                             bool detect_fpe,
722                             unsigned long int timeout_microseconds,
723                             bool attach_dbg,
724                             char* alt_stack );
725
726    // Destructor
727    ~signal_handler();
728
729    // access methods
730    static sigjmp_buf&      jump_buffer()
731    {
732        assert( !!s_active_handler );
733
734        return s_active_handler->m_sigjmp_buf;
735    }
736
737    static system_signal_exception&  sys_sig()
738    {
739        assert( !!s_active_handler );
740
741        return s_active_handler->m_sys_sig;
742    }
743
744private:
745    // Data members
746    signal_handler*         m_prev_handler;
747    unsigned long int       m_timeout_microseconds;
748
749    // Note: We intentionality do not catch SIGCHLD. Users have to deal with it themselves
750    signal_action           m_ILL_action;
751    signal_action           m_FPE_action;
752    signal_action           m_SEGV_action;
753    signal_action           m_BUS_action;
754    signal_action           m_CHLD_action;
755    signal_action           m_POLL_action;
756    signal_action           m_ABRT_action;
757    signal_action           m_ALRM_action;
758
759    sigjmp_buf              m_sigjmp_buf;
760    system_signal_exception m_sys_sig;
761
762    static signal_handler*  s_active_handler;
763};
764
765// !! need to be placed in thread specific storage
766typedef signal_handler* signal_handler_ptr;
767signal_handler* signal_handler::s_active_handler = signal_handler_ptr();
768
769//____________________________________________________________________________//
770
771signal_handler::signal_handler( bool catch_system_errors,
772                                bool detect_fpe,
773                                unsigned long int timeout_microseconds,
774                                bool attach_dbg,
775                                char* alt_stack )
776: m_prev_handler( s_active_handler )
777, m_timeout_microseconds( timeout_microseconds )
778, m_ILL_action ( SIGILL , catch_system_errors,      attach_dbg, alt_stack )
779, m_FPE_action ( SIGFPE , detect_fpe         ,      attach_dbg, alt_stack )
780, m_SEGV_action( SIGSEGV, catch_system_errors,      attach_dbg, alt_stack )
781, m_BUS_action ( SIGBUS , catch_system_errors,      attach_dbg, alt_stack )
782#ifdef BOOST_TEST_CATCH_SIGPOLL
783, m_POLL_action( SIGPOLL, catch_system_errors,      attach_dbg, alt_stack )
784#endif
785, m_ABRT_action( SIGABRT, catch_system_errors,      attach_dbg, alt_stack )
786, m_ALRM_action( SIGALRM, timeout_microseconds > 0, attach_dbg, alt_stack )
787{
788    s_active_handler = this;
789
790    if( m_timeout_microseconds > 0 ) {
791        ::alarm( 0 );
792        ::alarm( static_cast<unsigned int>(std::ceil(timeout_microseconds / 1E6) )); // alarm has a precision to the seconds
793    }
794
795#ifdef BOOST_TEST_USE_ALT_STACK
796    if( alt_stack ) {
797        stack_t sigstk;
798        std::memset( &sigstk, 0, sizeof(stack_t) );
799
800        BOOST_TEST_SYS_ASSERT( ::sigaltstack( 0, &sigstk ) != -1 );
801
802        if( sigstk.ss_flags & SS_DISABLE ) {
803            sigstk.ss_sp    = alt_stack;
804            sigstk.ss_size  = BOOST_TEST_ALT_STACK_SIZE;
805            sigstk.ss_flags = 0;
806            BOOST_TEST_SYS_ASSERT( ::sigaltstack( &sigstk, 0 ) != -1 );
807        }
808    }
809#endif
810}
811
812//____________________________________________________________________________//
813
814signal_handler::~signal_handler()
815{
816    assert( s_active_handler == this );
817
818    if( m_timeout_microseconds > 0 )
819        ::alarm( 0 );
820
821#ifdef BOOST_TEST_USE_ALT_STACK
822#ifdef __GNUC__
823    // We shouldn't need to explicitly initialize all the members here,
824    // but gcc warns if we don't, so add initializers for each of the
825    // members specified in the POSIX std:
826    stack_t sigstk = { 0, 0, 0 };
827#else
828    stack_t sigstk = { };
829#endif
830
831    sigstk.ss_size  = MINSIGSTKSZ;
832    sigstk.ss_flags = SS_DISABLE;
833    if( ::sigaltstack( &sigstk, 0 ) == -1 ) {
834        int error_n = errno;
835        std::cerr << "******** errors disabling the alternate stack:" << std::endl
836                  << "\t#error:" << error_n << std::endl
837                  << "\t" << std::strerror( error_n ) << std::endl;
838    }
839#endif
840
841    s_active_handler = m_prev_handler;
842}
843
844//____________________________________________________________________________//
845
846// ************************************************************************** //
847// **************       execution_monitor_signal_handler       ************** //
848// ************************************************************************** //
849
850extern "C" {
851
852static void boost_execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context )
853{
854    signal_handler::sys_sig()( info, context );
855
856    siglongjmp( signal_handler::jump_buffer(), sig );
857}
858
859//____________________________________________________________________________//
860
861static void boost_execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context )
862{
863    if( !debug::attach_debugger( false ) )
864        boost_execution_monitor_jumping_signal_handler( sig, info, context );
865
866    // debugger attached; it will handle the signal
867    BOOST_TEST_SYS_ASSERT( ::signal( sig, SIG_DFL ) != SIG_ERR );
868}
869
870//____________________________________________________________________________//
871
872}
873
874} // namespace detail
875
876// ************************************************************************** //
877// **************        execution_monitor::catch_signals      ************** //
878// ************************************************************************** //
879
880int
881execution_monitor::catch_signals( boost::function<int ()> const& F )
882{
883    using namespace detail;
884
885#if defined(__CYGWIN__)
886    p_catch_system_errors.value = false;
887#endif
888
889#ifdef BOOST_TEST_USE_ALT_STACK
890    if( !!p_use_alt_stack && !m_alt_stack )
891        m_alt_stack.reset( new char[BOOST_TEST_ALT_STACK_SIZE] );
892#else
893    p_use_alt_stack.value = false;
894#endif
895
896    signal_handler local_signal_handler( p_catch_system_errors,
897                                         p_catch_system_errors || (p_detect_fp_exceptions != fpe::BOOST_FPE_OFF),
898                                         p_timeout,
899                                         p_auto_start_dbg,
900                                         !p_use_alt_stack ? 0 : m_alt_stack.get() );
901
902    if( !sigsetjmp( signal_handler::jump_buffer(), 1 ) )
903        return detail::do_invoke( m_custom_translators , F );
904    else
905        BOOST_TEST_I_THROW( local_signal_handler.sys_sig() );
906}
907
908//____________________________________________________________________________//
909
910#elif defined(BOOST_SEH_BASED_SIGNAL_HANDLING)
911
912// ************************************************************************** //
913// **************   Microsoft structured exception handling    ************** //
914// ************************************************************************** //
915
916#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x0564))
917namespace { void _set_se_translator( void* ) {} }
918#endif
919
920namespace detail {
921
922// ************************************************************************** //
923// **************    boost::detail::system_signal_exception    ************** //
924// ************************************************************************** //
925
926class system_signal_exception {
927public:
928    // Constructor
929    explicit            system_signal_exception( execution_monitor* em )
930    : m_em( em )
931    , m_se_id( 0 )
932    , m_fault_address( 0 )
933    , m_dir( false )
934    , m_timeout( false )
935    {}
936
937    void                set_timed_out();
938    void                report() const;
939    int                 operator()( unsigned id, _EXCEPTION_POINTERS* exps );
940
941private:
942    // Data members
943    execution_monitor*  m_em;
944
945    unsigned            m_se_id;
946    void*               m_fault_address;
947    bool                m_dir;
948    bool                m_timeout;
949};
950
951//____________________________________________________________________________//
952
953#if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
954static void
955seh_catch_preventer( unsigned /* id */, _EXCEPTION_POINTERS* /* exps */ )
956{
957    throw;
958}
959#endif
960
961//____________________________________________________________________________//
962
963void
964system_signal_exception::set_timed_out()
965{
966    m_timeout = true;
967}
968
969//____________________________________________________________________________//
970
971int
972system_signal_exception::operator()( unsigned id, _EXCEPTION_POINTERS* exps )
973{
974    const unsigned MSFT_CPP_EXCEPT = 0xE06d7363; // EMSC
975
976    // C++ exception - allow to go through
977    if( id == MSFT_CPP_EXCEPT )
978        return EXCEPTION_CONTINUE_SEARCH;
979
980    // FPE detection is enabled, while system exception detection is not - check if this is actually FPE
981    if( !m_em->p_catch_system_errors ) {
982        if( !m_em->p_detect_fp_exceptions )
983            return EXCEPTION_CONTINUE_SEARCH;
984
985        switch( id ) {
986        case EXCEPTION_FLT_DIVIDE_BY_ZERO:
987        case EXCEPTION_FLT_STACK_CHECK:
988        case EXCEPTION_FLT_DENORMAL_OPERAND:
989        case EXCEPTION_FLT_INEXACT_RESULT:
990        case EXCEPTION_FLT_OVERFLOW:
991        case EXCEPTION_FLT_UNDERFLOW:
992        case EXCEPTION_FLT_INVALID_OPERATION:
993        case STATUS_FLOAT_MULTIPLE_FAULTS:
994        case STATUS_FLOAT_MULTIPLE_TRAPS:
995            break;
996        default:
997            return EXCEPTION_CONTINUE_SEARCH;
998        }
999    }
1000
1001    if( !!m_em->p_auto_start_dbg && debug::attach_debugger( false ) ) {
1002        m_em->p_catch_system_errors.value = false;
1003#if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
1004        _set_se_translator( &seh_catch_preventer );
1005#endif
1006        return EXCEPTION_CONTINUE_EXECUTION;
1007    }
1008
1009    m_se_id = id;
1010    if( m_se_id == EXCEPTION_ACCESS_VIOLATION && exps->ExceptionRecord->NumberParameters == 2 ) {
1011        m_fault_address = (void*)exps->ExceptionRecord->ExceptionInformation[1];
1012        m_dir           = exps->ExceptionRecord->ExceptionInformation[0] == 0;
1013    }
1014
1015    return EXCEPTION_EXECUTE_HANDLER;
1016}
1017
1018//____________________________________________________________________________//
1019
1020void
1021system_signal_exception::report() const
1022{
1023    switch( m_se_id ) {
1024    // cases classified as system_fatal_error
1025    case EXCEPTION_ACCESS_VIOLATION: {
1026        if( !m_fault_address )
1027            detail::report_error( execution_exception::system_fatal_error, "memory access violation" );
1028        else
1029            detail::report_error(
1030                execution_exception::system_fatal_error,
1031                    "memory access violation occurred at address 0x%08lx, while attempting to %s",
1032                    m_fault_address,
1033                    m_dir ? " read inaccessible data"
1034                          : " write to an inaccessible (or protected) address"
1035                    );
1036        break;
1037    }
1038
1039    case EXCEPTION_ILLEGAL_INSTRUCTION:
1040        detail::report_error( execution_exception::system_fatal_error, "illegal instruction" );
1041        break;
1042
1043    case EXCEPTION_PRIV_INSTRUCTION:
1044        detail::report_error( execution_exception::system_fatal_error, "tried to execute an instruction whose operation is not allowed in the current machine mode" );
1045        break;
1046
1047    case EXCEPTION_IN_PAGE_ERROR:
1048        detail::report_error( execution_exception::system_fatal_error, "access to a memory page that is not present" );
1049        break;
1050
1051    case EXCEPTION_STACK_OVERFLOW:
1052        detail::report_error( execution_exception::system_fatal_error, "stack overflow" );
1053        break;
1054
1055    case EXCEPTION_NONCONTINUABLE_EXCEPTION:
1056        detail::report_error( execution_exception::system_fatal_error, "tried to continue execution after a non continuable exception occurred" );
1057        break;
1058
1059    // cases classified as (non-fatal) system_trap
1060    case EXCEPTION_DATATYPE_MISALIGNMENT:
1061        detail::report_error( execution_exception::system_error, "data misalignment" );
1062        break;
1063
1064    case EXCEPTION_INT_DIVIDE_BY_ZERO:
1065        detail::report_error( execution_exception::system_error, "integer divide by zero" );
1066        break;
1067
1068    case EXCEPTION_INT_OVERFLOW:
1069        detail::report_error( execution_exception::system_error, "integer overflow" );
1070        break;
1071
1072    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1073        detail::report_error( execution_exception::system_error, "array bounds exceeded" );
1074        break;
1075
1076    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
1077        detail::report_error( execution_exception::system_error, "floating point divide by zero" );
1078        break;
1079
1080    case EXCEPTION_FLT_STACK_CHECK:
1081        detail::report_error( execution_exception::system_error,
1082                              "stack overflowed or underflowed as the result of a floating-point operation" );
1083        break;
1084
1085    case EXCEPTION_FLT_DENORMAL_OPERAND:
1086        detail::report_error( execution_exception::system_error,
1087                              "operand of floating point operation is denormal" );
1088        break;
1089
1090    case EXCEPTION_FLT_INEXACT_RESULT:
1091        detail::report_error( execution_exception::system_error,
1092                              "result of a floating-point operation cannot be represented exactly" );
1093        break;
1094
1095    case EXCEPTION_FLT_OVERFLOW:
1096        detail::report_error( execution_exception::system_error,
1097                              "exponent of a floating-point operation is greater than the magnitude allowed by the corresponding type" );
1098        break;
1099
1100    case EXCEPTION_FLT_UNDERFLOW:
1101        detail::report_error( execution_exception::system_error,
1102                              "exponent of a floating-point operation is less than the magnitude allowed by the corresponding type" );
1103        break;
1104
1105    case EXCEPTION_FLT_INVALID_OPERATION:
1106        detail::report_error( execution_exception::system_error, "floating point error" );
1107        break;
1108
1109    case STATUS_FLOAT_MULTIPLE_FAULTS:
1110        detail::report_error( execution_exception::system_error, "multiple floating point errors" );
1111        break;
1112
1113    case STATUS_FLOAT_MULTIPLE_TRAPS:
1114        detail::report_error( execution_exception::system_error, "multiple floating point errors" );
1115        break;
1116
1117    case EXCEPTION_BREAKPOINT:
1118        detail::report_error( execution_exception::system_error, "breakpoint encountered" );
1119        break;
1120
1121    default:
1122        if( m_timeout ) {
1123            detail::report_error(execution_exception::timeout_error, "timeout while executing function");
1124        }
1125        else {
1126            detail::report_error( execution_exception::system_error, "unrecognized exception. Id: 0x%08lx", m_se_id );
1127        }
1128        break;
1129    }
1130}
1131
1132//____________________________________________________________________________//
1133
1134// ************************************************************************** //
1135// **************          assert_reporting_function           ************** //
1136// ************************************************************************** //
1137
1138int BOOST_TEST_CALL_DECL
1139assert_reporting_function( int reportType, char* userMessage, int* )
1140{
1141    // write this way instead of switch to avoid unreachable statements
1142    if( reportType == BOOST_TEST_CRT_ASSERT || reportType == BOOST_TEST_CRT_ERROR )
1143        detail::report_error( reportType == BOOST_TEST_CRT_ASSERT ? execution_exception::user_error : execution_exception::system_error, userMessage );
1144
1145    return 0;
1146} // assert_reporting_function
1147
1148//____________________________________________________________________________//
1149
1150void BOOST_TEST_CALL_DECL
1151invalid_param_handler( wchar_t const* /* expr */,
1152                       wchar_t const* /* func */,
1153                       wchar_t const* /* file */,
1154                       unsigned       /* line */,
1155                       uintptr_t      /* reserved */)
1156{
1157    detail::report_error( execution_exception::user_error,
1158                          "Invalid parameter detected by C runtime library" );
1159}
1160
1161//____________________________________________________________________________//
1162
1163} // namespace detail
1164
1165// ************************************************************************** //
1166// **************        execution_monitor::catch_signals      ************** //
1167// ************************************************************************** //
1168
1169int
1170execution_monitor::catch_signals( boost::function<int ()> const& F )
1171{
1172    _invalid_parameter_handler old_iph = _invalid_parameter_handler();
1173    BOOST_TEST_CRT_HOOK_TYPE old_crt_hook = 0;
1174
1175    if( p_catch_system_errors ) {
1176        old_crt_hook = BOOST_TEST_CRT_SET_HOOK( &detail::assert_reporting_function );
1177
1178        old_iph = _set_invalid_parameter_handler(
1179            reinterpret_cast<_invalid_parameter_handler>( &detail::invalid_param_handler ) );
1180    } else if( !p_detect_fp_exceptions ) {
1181#if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
1182        _set_se_translator( &detail::seh_catch_preventer );
1183#endif
1184    }
1185
1186#if defined(BOOST_TEST_WIN32_WAITABLE_TIMERS)
1187    HANDLE htimer = INVALID_HANDLE_VALUE;
1188    BOOL bTimerSuccess = FALSE;
1189
1190    if( p_timeout ) {
1191        htimer = ::CreateWaitableTimer(
1192            NULL,
1193            TRUE,
1194            NULL); // naming the timer might create collisions
1195
1196        if( htimer != INVALID_HANDLE_VALUE ) {
1197            LARGE_INTEGER liDueTime;
1198            liDueTime.QuadPart = - static_cast<LONGLONG>(p_timeout) * 10ll; // resolution of 100 ns
1199
1200            bTimerSuccess = ::SetWaitableTimer(
1201                htimer,
1202                &liDueTime,
1203                0,
1204                0,
1205                0,
1206                FALSE);           // Do not restore a suspended system
1207        }
1208    }
1209#endif
1210
1211    detail::system_signal_exception SSE( this );
1212
1213    int ret_val = 0;
1214    // clang windows workaround: this not available in __finally scope
1215    bool l_catch_system_errors = p_catch_system_errors;
1216
1217    __try {
1218        __try {
1219            ret_val = detail::do_invoke( m_custom_translators, F );
1220        }
1221        __except( SSE( GetExceptionCode(), GetExceptionInformation() ) ) {
1222            throw SSE;
1223        }
1224
1225        // we check for time outs: we do not have any signaling facility on Win32
1226        // however, we signal a timeout as a hard error as for the other operating systems
1227        // and throw the signal error handler
1228        if( bTimerSuccess && htimer != INVALID_HANDLE_VALUE) {
1229            if (::WaitForSingleObject(htimer, 0) == WAIT_OBJECT_0) {
1230                SSE.set_timed_out();
1231                throw SSE;
1232            }
1233        }
1234
1235    }
1236    __finally {
1237
1238#if defined(BOOST_TEST_WIN32_WAITABLE_TIMERS)
1239        if( htimer != INVALID_HANDLE_VALUE ) {
1240            ::CloseHandle(htimer);
1241        }
1242#endif
1243
1244        if( l_catch_system_errors ) {
1245            BOOST_TEST_CRT_SET_HOOK( old_crt_hook );
1246
1247           _set_invalid_parameter_handler( old_iph );
1248        }
1249    }
1250
1251    return ret_val;
1252}
1253
1254//____________________________________________________________________________//
1255
1256#else  // default signal handler
1257
1258namespace detail {
1259
1260class system_signal_exception {
1261public:
1262    void   report() const {}
1263};
1264
1265} // namespace detail
1266
1267int
1268execution_monitor::catch_signals( boost::function<int ()> const& F )
1269{
1270    return detail::do_invoke( m_custom_translators , F );
1271}
1272
1273//____________________________________________________________________________//
1274
1275#endif  // choose signal handler
1276
1277// ************************************************************************** //
1278// **************              execution_monitor               ************** //
1279// ************************************************************************** //
1280
1281execution_monitor::execution_monitor()
1282: p_catch_system_errors( true )
1283, p_auto_start_dbg( false )
1284, p_timeout( 0 )
1285, p_use_alt_stack( true )
1286, p_detect_fp_exceptions( fpe::BOOST_FPE_OFF )
1287{}
1288
1289//____________________________________________________________________________//
1290
1291int
1292execution_monitor::execute( boost::function<int ()> const& F )
1293{
1294    if( debug::under_debugger() )
1295        p_catch_system_errors.value = false;
1296
1297    BOOST_TEST_I_TRY {
1298        detail::fpe_except_guard G( p_detect_fp_exceptions );
1299        boost::ignore_unused( G );
1300
1301        return catch_signals( F );
1302    }
1303
1304#ifndef BOOST_NO_EXCEPTIONS
1305
1306    //  Catch-clause reference arguments are a bit different from function
1307    //  arguments (ISO 15.3 paragraphs 18 & 19).  Apparently const isn't
1308    //  required.  Programmers ask for const anyhow, so we supply it.  That's
1309    //  easier than answering questions about non-const usage.
1310
1311    catch( char const* ex )
1312      { detail::report_error( execution_exception::cpp_exception_error,
1313                              "C string: %s", ex ); }
1314    catch( std::string const& ex )
1315      { detail::report_error( execution_exception::cpp_exception_error,
1316                              "std::string: %s", ex.c_str() ); }
1317
1318    // boost::exception (before std::exception, with extended diagnostic)
1319    catch( boost::exception const& ex )
1320      { detail::report_error( execution_exception::cpp_exception_error,
1321                              &ex,
1322                              "%s", boost::diagnostic_information(ex).c_str() ); }
1323
1324    //  std:: exceptions
1325#if defined(BOOST_NO_TYPEID) || defined(BOOST_NO_RTTI)
1326#define CATCH_AND_REPORT_STD_EXCEPTION( ex_name )                           \
1327    catch( ex_name const& ex )                                              \
1328       { detail::report_error( execution_exception::cpp_exception_error,    \
1329                          current_exception_cast<boost::exception const>(), \
1330                          #ex_name ": %s", ex.what() ); }                   \
1331/**/
1332#else
1333#define CATCH_AND_REPORT_STD_EXCEPTION( ex_name )                           \
1334    catch( ex_name const& ex )                                              \
1335        { detail::report_error( execution_exception::cpp_exception_error,   \
1336                          current_exception_cast<boost::exception const>(), \
1337                          "%s: %s", detail::typeid_name(ex).c_str(), ex.what() ); } \
1338/**/
1339#endif
1340
1341    CATCH_AND_REPORT_STD_EXCEPTION( std::bad_alloc )
1342    CATCH_AND_REPORT_STD_EXCEPTION( std::bad_cast )
1343    CATCH_AND_REPORT_STD_EXCEPTION( std::bad_typeid )
1344    CATCH_AND_REPORT_STD_EXCEPTION( std::bad_exception )
1345    CATCH_AND_REPORT_STD_EXCEPTION( std::domain_error )
1346    CATCH_AND_REPORT_STD_EXCEPTION( std::invalid_argument )
1347    CATCH_AND_REPORT_STD_EXCEPTION( std::length_error )
1348    CATCH_AND_REPORT_STD_EXCEPTION( std::out_of_range )
1349    CATCH_AND_REPORT_STD_EXCEPTION( std::range_error )
1350    CATCH_AND_REPORT_STD_EXCEPTION( std::overflow_error )
1351    CATCH_AND_REPORT_STD_EXCEPTION( std::underflow_error )
1352    CATCH_AND_REPORT_STD_EXCEPTION( std::logic_error )
1353    CATCH_AND_REPORT_STD_EXCEPTION( std::runtime_error )
1354    CATCH_AND_REPORT_STD_EXCEPTION( std::exception )
1355#undef CATCH_AND_REPORT_STD_EXCEPTION
1356
1357    // system errors
1358    catch( system_error const& ex )
1359      { detail::report_error( execution_exception::cpp_exception_error,
1360                              "system_error produced by: %s: %s", ex.p_failed_exp, std::strerror( ex.p_errno ) ); }
1361    catch( detail::system_signal_exception const& ex )
1362      { ex.report(); }
1363
1364    // not an error
1365    catch( execution_aborted const& )
1366      { return 0; }
1367
1368    // just forward
1369    catch( execution_exception const& )
1370      { throw; }
1371
1372    // unknown error
1373    catch( ... )
1374      { detail::report_error( execution_exception::cpp_exception_error, "unknown type" ); }
1375
1376#endif // !BOOST_NO_EXCEPTIONS
1377
1378    BOOST_TEST_UNREACHABLE_RETURN(0);  // never reached; supplied to quiet compiler warnings
1379} // execute
1380
1381//____________________________________________________________________________//
1382
1383namespace detail {
1384
1385struct forward {
1386    explicit    forward( boost::function<void ()> const& F ) : m_F( F ) {}
1387
1388    int         operator()() { m_F(); return 0; }
1389
1390    boost::function<void ()> const& m_F;
1391};
1392
1393} // namespace detail
1394void
1395execution_monitor::vexecute( boost::function<void ()> const& F )
1396{
1397    execute( detail::forward( F ) );
1398}
1399
1400// ************************************************************************** //
1401// **************                  system_error                ************** //
1402// ************************************************************************** //
1403
1404system_error::system_error( char const* exp )
1405#ifdef UNDER_CE
1406: p_errno( GetLastError() )
1407#else
1408: p_errno( errno )
1409#endif
1410, p_failed_exp( exp )
1411{}
1412
1413//____________________________________________________________________________//
1414
1415// ************************************************************************** //
1416// **************              execution_exception             ************** //
1417// ************************************************************************** //
1418
1419execution_exception::execution_exception( error_code ec_, const_string what_msg_, location const& location_ )
1420: m_error_code( ec_ )
1421, m_what( what_msg_.empty() ? BOOST_TEST_L( "uncaught exception, system error or abort requested" ) : what_msg_ )
1422, m_location( location_ )
1423{}
1424
1425//____________________________________________________________________________//
1426
1427execution_exception::location::location( char const* file_name, size_t line_num, char const* func )
1428: m_file_name( file_name ? file_name : "unknown location" )
1429, m_line_num( line_num )
1430, m_function( func )
1431{}
1432
1433execution_exception::location::location(const_string file_name, size_t line_num, char const* func )
1434: m_file_name( file_name )
1435, m_line_num( line_num )
1436, m_function( func )
1437{}
1438
1439//____________________________________________________________________________//
1440
1441// ************************************************************************** //
1442// **************Floating point exception management interface ************** //
1443// ************************************************************************** //
1444
1445namespace fpe {
1446
1447unsigned
1448enable( unsigned mask )
1449{
1450    boost::ignore_unused(mask);
1451#if defined(BOOST_TEST_FPE_SUPPORT_WITH_SEH__)
1452    _clearfp();
1453
1454#if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
1455    unsigned old_cw = ::_controlfp( 0, 0 );
1456    ::_controlfp( old_cw & ~mask, BOOST_FPE_ALL );
1457#else
1458    unsigned old_cw;
1459    if( ::_controlfp_s( &old_cw, 0, 0 ) != 0 )
1460        return BOOST_FPE_INV;
1461
1462    // Set the control word
1463    if( ::_controlfp_s( 0, old_cw & ~mask, BOOST_FPE_ALL ) != 0 )
1464        return BOOST_FPE_INV;
1465#endif
1466    return ~old_cw & BOOST_FPE_ALL;
1467
1468#elif defined(BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__)
1469    // same macro definition as in execution_monitor.hpp
1470    if (BOOST_FPE_ALL == BOOST_FPE_OFF)
1471        /* Not Implemented */
1472        return BOOST_FPE_OFF;
1473    feclearexcept(BOOST_FPE_ALL);
1474    int res = feenableexcept( mask );
1475    return res == -1 ? (unsigned)BOOST_FPE_INV : (unsigned)res;
1476#else
1477    /* Not Implemented  */
1478    return BOOST_FPE_OFF;
1479#endif
1480}
1481
1482//____________________________________________________________________________//
1483
1484unsigned
1485disable( unsigned mask )
1486{
1487    boost::ignore_unused(mask);
1488
1489#if defined(BOOST_TEST_FPE_SUPPORT_WITH_SEH__)
1490    _clearfp();
1491#if BOOST_WORKAROUND( BOOST_MSVC, <= 1310)
1492    unsigned old_cw = ::_controlfp( 0, 0 );
1493    ::_controlfp( old_cw | mask, BOOST_FPE_ALL );
1494#else
1495    unsigned old_cw;
1496    if( ::_controlfp_s( &old_cw, 0, 0 ) != 0 )
1497        return BOOST_FPE_INV;
1498
1499    // Set the control word
1500    if( ::_controlfp_s( 0, old_cw | mask, BOOST_FPE_ALL ) != 0 )
1501        return BOOST_FPE_INV;
1502#endif
1503    return ~old_cw & BOOST_FPE_ALL;
1504
1505#elif defined(BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__)
1506    if (BOOST_FPE_ALL == BOOST_FPE_OFF)
1507        /* Not Implemented */
1508        return BOOST_FPE_INV;
1509    feclearexcept(BOOST_FPE_ALL);
1510    int res = fedisableexcept( mask );
1511    return res == -1 ? (unsigned)BOOST_FPE_INV : (unsigned)res;
1512#else
1513    /* Not Implemented */
1514    return BOOST_FPE_INV;
1515#endif
1516}
1517
1518//____________________________________________________________________________//
1519
1520} // namespace fpe
1521
1522} // namespace boost
1523
1524#include <boost/test/detail/enable_warnings.hpp>
1525
1526#endif // BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER
1527