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