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

source code of include/boost/test/impl/execution_monitor.ipp