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 55namespace 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> 62using std::va_list; 63#endif 64 65// to use vsnprintf 66#if defined(__QNXNTO__) 67# include <stdio.h> 68using 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 108typedef void* _invalid_parameter_handler; 109 110inline _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 120namespace { 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 193namespace boost { 194 195// ************************************************************************** // 196// ************** throw_exception ************** // 197// ************************************************************************** // 198 199#ifdef BOOST_NO_EXCEPTIONS 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_EXCEPTIONS 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 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 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_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) 313template<typename T> 314std::string 315typeid_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 329namespace detail { 330 331// ************************************************************************** // 332// ************** boost::detail::system_signal_exception ************** // 333// ************************************************************************** // 334 335class system_signal_exception { 336public: 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 351private: 352 // Data members 353 siginfo_t* m_sig_info; // system signal detailed info 354 void* m_context; // signal context 355}; 356 357//____________________________________________________________________________// 358 359void 360system_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 614extern "C" { 615static void boost_execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context ); 616static void boost_execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context ); 617} 618 619class signal_action { 620 typedef struct sigaction* sigaction_ptr; 621public: 622 //Constructor 623 signal_action(); 624 signal_action( int sig, bool install, bool attach_dbg, char* alt_stack ); 625 ~signal_action(); 626 627private: 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 637signal_action::signal_action() 638: m_installed( false ) 639{} 640 641//____________________________________________________________________________// 642 643signal_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 674signal_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 686class signal_handler { 687public: 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 709private: 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 731typedef signal_handler* signal_handler_ptr; 732signal_handler* signal_handler::s_active_handler = signal_handler_ptr(); 733 734//____________________________________________________________________________// 735 736signal_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 775signal_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 811extern "C" { 812 813static 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 822static 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 841int 842execution_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)) 878namespace { void _set_se_translator( void* ) {} } 879#endif 880 881namespace detail { 882 883// ************************************************************************** // 884// ************** boost::detail::system_signal_exception ************** // 885// ************************************************************************** // 886 887class system_signal_exception { 888public: 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 900private: 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) 912static void 913seh_catch_preventer( unsigned /* id */, _EXCEPTION_POINTERS* /* exps */ ) 914{ 915 throw; 916} 917#endif 918 919//____________________________________________________________________________// 920 921int 922system_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 970void 971system_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 1083int BOOST_TEST_CALL_DECL 1084assert_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 1095void BOOST_TEST_CALL_DECL 1096invalid_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 1114int 1115execution_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 1160namespace detail { 1161 1162class system_signal_exception { 1163public: 1164 void report() const {} 1165}; 1166 1167} // namespace detail 1168 1169int 1170execution_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 1183execution_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 1193int 1194execution_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 1295namespace detail { 1296 1297struct 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 1306void 1307execution_monitor::vexecute( boost::function<void ()> const& F ) 1308{ 1309 execute( detail::forward( F ) ); 1310} 1311 1312// ************************************************************************** // 1313// ************** system_error ************** // 1314// ************************************************************************** // 1315 1316system_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 1331execution_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 1339execution_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 1345execution_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 1357namespace fpe { 1358 1359unsigned 1360enable( 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 1396unsigned 1397disable( 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 1439