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