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