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