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

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