Ticket #5277: execution_monitor.ipp

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