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 52 namespace 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> 59 using 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) 88 typedef 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 133 typedef void* _invalid_parameter_handler; 134 135 inline _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 145 namespace { 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 205 namespace boost { 206 207 // ************************************************************************** // 208 // ************** report_error ************** // 209 // ************************************************************************** // 210 211 namespace 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 223 template <typename ErrorInfo> 224 typename ErrorInfo::value_type 225 extract( 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 237 static void 238 report_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 255 static void 256 report_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 266 static void 267 report_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 277 template<typename Tr,typename Functor> 278 inline int 279 do_invoke( Tr const& tr, Functor const& F ) 280 { 281 return tr ? (*tr)( F ) : F(); 282 } 283 284 //____________________________________________________________________________// 285 286 } // namespace detail 287 288 #if defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING) 289 290 // ************************************************************************** // 291 // ************** Sigaction based signal handling ************** // 292 // ************************************************************************** // 293 294 namespace detail { 295 296 // ************************************************************************** // 297 // ************** boost::detail::system_signal_exception ************** // 298 // ************************************************************************** // 299 300 class system_signal_exception { 301 public: 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 316 private: 317 // Data members 318 siginfo_t* m_sig_info; // system signal detailed info 319 void* m_context; // signal context 320 }; 321 322 //____________________________________________________________________________// 323 324 void 325 system_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 620 extern "C" { 621 static void execution_monitor_jumping_signal_handler( int sig, siginfo_t* info, void* context ); 622 static void execution_monitor_attaching_signal_handler( int sig, siginfo_t* info, void* context ); 623 } 624 625 class signal_action { 626 typedef struct sigaction* sigaction_ptr; 627 public: 628 //Constructor 629 signal_action(); 630 signal_action( int sig, bool install, bool attach_dbg, char* alt_stack ); 631 ~signal_action(); 632 633 private: 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 643 signal_action::signal_action() 644 : m_installed( false ) 645 {} 646 647 //____________________________________________________________________________// 648 649 signal_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 680 signal_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 692 class signal_handler { 693 public: 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 715 private: 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 736 typedef signal_handler* signal_handler_ptr; 737 signal_handler* signal_handler::s_active_handler = signal_handler_ptr(); 738 739 //____________________________________________________________________________// 740 741 signal_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 783 signal_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 814 extern "C" { 815 816 static 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 831 static 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 843 static 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 865 int 866 execution_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)) 899 namespace { void _set_se_translator( void* ) {} } 900 #endif 901 902 namespace detail { 903 904 // ************************************************************************** // 905 // ************** boost::detail::system_signal_exception ************** // 906 // ************************************************************************** // 907 908 class system_signal_exception { 909 public: 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 921 private: 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 930 static void 931 seh_catch_preventer( unsigned int /* id */, _EXCEPTION_POINTERS* /* exps */ ) 932 { 933 throw; 934 } 935 936 //____________________________________________________________________________// 937 938 int 939 system_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 964 void 965 system_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 1071 int BOOST_TEST_CALL_DECL 1072 assert_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 1090 void BOOST_TEST_CALL_DECL 1091 invalid_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 1103 void BOOST_TEST_CALL_DECL 1104 switch_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 1133 int 1134 execution_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 1181 namespace detail { 1182 1183 class system_signal_exception { 1184 public: 1185 void report() const {} 1186 }; 1187 1188 } // namespace detail 1189 1190 int 1191 execution_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 1204 int 1205 execution_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 1331 system_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 1346 execution_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 1354 execution_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