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