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