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