Ticket #7726: execution_monitor.ipp

File execution_monitor.ipp, 49.9 KB (added by p.brockamp@…, 10 years ago)

Test

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