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