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