annotate DEPENDENCIES/generic/include/boost/test/impl/execution_monitor.ipp @ 133:4acb5d8d80b6 tip

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