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