|
1 // (C) Copyright Gennadiy Rozental 2001-2005. |
|
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: execution_monitor.ipp,v $ |
|
10 // |
|
11 // Version : $Revision: 1.13 $ |
|
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 * © Portions copyright (c) 2006-2007 Nokia Corporation. All rights reserved. |
|
25 */ |
|
26 |
|
27 #ifndef BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER |
|
28 #define BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER |
|
29 |
|
30 // Boost.Test |
|
31 #include <boost/test/detail/config.hpp> |
|
32 #include <boost/test/detail/workaround.hpp> |
|
33 #include <boost/test/execution_monitor.hpp> |
|
34 |
|
35 // Boost |
|
36 #include <boost/cstdlib.hpp> // for exit codes |
|
37 #include <boost/config.hpp> // for workarounds |
|
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 |
|
49 #ifdef BOOST_NO_STDC_NAMESPACE |
|
50 namespace std { using ::strlen; using ::strncat; } |
|
51 #endif |
|
52 |
|
53 // Microsoft + other compatible compilers such as Intel |
|
54 |
|
55 #if !defined(BOOST_DISABLE_WIN32) && \ |
|
56 !defined(__BORLANDC__) && \ |
|
57 (defined(_MSC_VER) && !defined(__COMO__)) || \ |
|
58 !(defined(__SYMBIAN32__)) |
|
59 |
|
60 |
|
61 //(BOOST_WORKAROUND(__MWERKS__, >= 0x3000) && defined(__INTEL__)) && \ |
|
62 |
|
63 # define BOOST_MS_STRUCTURED_EXCEPTION_HANDLING |
|
64 |
|
65 # ifndef _WIN32_WINNT |
|
66 # ifdef _WINBASE_ |
|
67 # warning Debugger check disabled. Either define _WIN32_WINNT or include Boost.Test header in front of winbase.h |
|
68 # else |
|
69 # define BOOST_TEST_DEBUGGER_CHECK |
|
70 # define _WIN32_WINNT 0x0400 |
|
71 # endif |
|
72 # endif |
|
73 |
|
74 # include <wtypes.h> |
|
75 # include <winbase.h> |
|
76 # include <excpt.h> |
|
77 # include <eh.h> |
|
78 |
|
79 # if !defined(NDEBUG) && !defined(__MWERKS__) // __MWERKS__ does not seem to supply implementation of C runtime debug hooks, causing linking errors |
|
80 # define BOOST_MS_CRT_DEBUG_HOOKS |
|
81 # include <crtdbg.h> |
|
82 # endif |
|
83 |
|
84 #elif (defined(__BORLANDC__) && defined(_Windows) && !defined(BOOST_DISABLE_WIN32)) |
|
85 |
|
86 # define BOOST_MS_STRUCTURED_EXCEPTION_HANDLING |
|
87 # include <windows.h> // Borland 5.5.1 has its own way of doing things. |
|
88 |
|
89 #elif defined(BOOST_HAS_SIGACTION) |
|
90 |
|
91 # define BOOST_SIGACTION_BASED_SIGNAL_HANDLING |
|
92 |
|
93 # include <unistd.h> |
|
94 # include <signal.h> |
|
95 # include <setjmp.h> |
|
96 |
|
97 #else |
|
98 |
|
99 # define BOOST_NO_SIGNAL_HANDLING |
|
100 |
|
101 #endif |
|
102 |
|
103 #include <boost/test/detail/suppress_warnings.hpp> |
|
104 |
|
105 //____________________________________________________________________________// |
|
106 |
|
107 namespace boost { |
|
108 |
|
109 namespace detail { |
|
110 |
|
111 using unit_test::const_string; |
|
112 |
|
113 // boost::execution_monitor::execute() calls boost::detail::report_error(...) to |
|
114 // report any caught exception and throw execution_exception |
|
115 |
|
116 const std::size_t REPORT_ERROR_BUFFER_SIZE = 512; |
|
117 |
|
118 static void report_error( |
|
119 execution_exception::error_code ec, |
|
120 const_string msg1, // first part of the message |
|
121 const_string msg2 = "" ); // second part of the message; sum length msg1 + msg2 should not |
|
122 // exceed REPORT_ERROR_BUFFER_SIZE; never concatenate messages |
|
123 // manually, cause it should work even in case of memory lack |
|
124 |
|
125 //____________________________________________________________________________// |
|
126 |
|
127 // Declaration for Microsoft structured exception handling (unix alternative - signal) |
|
128 #ifdef BOOST_MS_STRUCTURED_EXCEPTION_HANDLING |
|
129 |
|
130 // this class defined per the Microsoft structured exception documentation |
|
131 class ms_se_exception { |
|
132 public: |
|
133 // Constructor |
|
134 EXPORT_C explicit ms_se_exception( unsigned int n ) |
|
135 : m_se_id( n ) {} |
|
136 |
|
137 // Destructor |
|
138 ~ms_se_exception() {} |
|
139 |
|
140 // access methods |
|
141 EXPORT_C unsigned int id() const { return m_se_id; } |
|
142 |
|
143 private: |
|
144 // Data members |
|
145 unsigned int m_se_id; |
|
146 }; |
|
147 |
|
148 //____________________________________________________________________________// |
|
149 |
|
150 void BOOST_TEST_CALL_DECL ms_se_trans_func( unsigned int id, _EXCEPTION_POINTERS* exps ); |
|
151 void BOOST_TEST_CALL_DECL ms_se_forward_func( unsigned int id, _EXCEPTION_POINTERS* exps ); |
|
152 static void report_ms_se_error( unsigned int id ); |
|
153 |
|
154 //____________________________________________________________________________// |
|
155 |
|
156 // Declarations for unix-style signal handling |
|
157 #elif defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING) |
|
158 |
|
159 class unix_signal_exception { |
|
160 typedef execution_exception::error_code error_code_type; |
|
161 public: |
|
162 // Constructor |
|
163 EXPORT_C unix_signal_exception( execution_exception::error_code ec, const_string em ) |
|
164 : m_error_code( ec ), m_error_message( em ) {} |
|
165 |
|
166 // Destructor |
|
167 ~unix_signal_exception() {} |
|
168 |
|
169 // access methods |
|
170 EXPORT_C error_code_type error_code() const { return m_error_code; } |
|
171 EXPORT_C const_string error_message() const { return m_error_message; } |
|
172 private: |
|
173 // Data members |
|
174 error_code_type m_error_code; |
|
175 const_string m_error_message; |
|
176 }; |
|
177 |
|
178 #endif |
|
179 |
|
180 //____________________________________________________________________________// |
|
181 |
|
182 #if defined(BOOST_MS_CRT_DEBUG_HOOKS) |
|
183 |
|
184 EXPORT_C int |
|
185 assert_reporting_function( int reportType, char* userMessage, int* retVal ) |
|
186 { |
|
187 switch( reportType ) { |
|
188 case _CRT_ASSERT: |
|
189 detail::report_error( execution_exception::user_error, userMessage ); |
|
190 |
|
191 return 1; // return value and retVal are not important since we never reach this line |
|
192 case _CRT_ERROR: |
|
193 detail::report_error( execution_exception::system_error, userMessage ); |
|
194 |
|
195 return 1; // return value and retVal are not important since we never reach this line |
|
196 default: |
|
197 return 0; // use usual reporting method |
|
198 } |
|
199 } |
|
200 |
|
201 #endif |
|
202 |
|
203 } // namespace detail |
|
204 |
|
205 // ************************************************************************** // |
|
206 // ************** execution_monitor ************** // |
|
207 // ************************************************************************** // |
|
208 |
|
209 EXPORT_C int |
|
210 execution_monitor::execute( unit_test::callback0<int> const& F, bool catch_system_errors, int timeout ) |
|
211 { |
|
212 using unit_test::const_string; |
|
213 |
|
214 # ifdef BOOST_TEST_DEBUGGER_CHECK |
|
215 if( IsDebuggerPresent() ) |
|
216 catch_system_errors = false; |
|
217 #endif |
|
218 |
|
219 #if defined(BOOST_MS_STRUCTURED_EXCEPTION_HANDLING) && !defined(__BORLANDC__) |
|
220 if( catch_system_errors ) |
|
221 _set_se_translator( detail::ms_se_trans_func ); |
|
222 else |
|
223 _set_se_translator( detail::ms_se_forward_func ); |
|
224 #endif |
|
225 |
|
226 #ifdef BOOST_MS_CRT_DEBUG_HOOKS |
|
227 if( catch_system_errors ) |
|
228 _CrtSetReportHook( &detail::assert_reporting_function ); |
|
229 #endif |
|
230 |
|
231 try { |
|
232 return catch_signals( F, catch_system_errors, timeout ); |
|
233 } |
|
234 |
|
235 // Catch-clause reference arguments are a bit different from function |
|
236 // arguments (ISO 15.3 paragraphs 18 & 19). Apparently const isn't |
|
237 // required. Programmers ask for const anyhow, so we supply it. That's |
|
238 // easier than answering questions about non-const usage. |
|
239 |
|
240 catch( char const* ex ) |
|
241 { detail::report_error( execution_exception::cpp_exception_error, "C string: ", ex ); } |
|
242 catch( std::string const& ex ) |
|
243 { detail::report_error( execution_exception::cpp_exception_error, "std::string: ", ex.c_str() ); } |
|
244 |
|
245 // std:: exceptions |
|
246 |
|
247 catch( std::bad_alloc const& ex ) |
|
248 { detail::report_error( execution_exception::cpp_exception_error, "std::bad_alloc: ", ex.what() ); } |
|
249 #ifndef __SYMBIAN32__ |
|
250 #if BOOST_WORKAROUND(__BORLANDC__, <= 0x0551) |
|
251 catch( std::bad_cast const& ex ) |
|
252 { detail::report_error( execution_exception::cpp_exception_error, "std::bad_cast" ); } |
|
253 catch( std::bad_typeid const& ex ) |
|
254 { detail::report_error( execution_exception::cpp_exception_error, "std::bad_typeid" ); } |
|
255 #else |
|
256 #endif //__SYMBIAN32__ |
|
257 catch( std::bad_cast const& ex ) |
|
258 { detail::report_error( execution_exception::cpp_exception_error, "std::bad_cast: ", ex.what() ); } |
|
259 catch( std::bad_typeid const& ex ) |
|
260 { detail::report_error( execution_exception::cpp_exception_error, "std::bad_typeid: ", ex.what() ); } |
|
261 #ifndef __SYMBIAN32__ |
|
262 #endif //BOOST_WORKAROUND |
|
263 #endif//__SYMBIAN32__ |
|
264 |
|
265 catch( std::bad_exception const& ex ) |
|
266 { detail::report_error( execution_exception::cpp_exception_error, "std::bad_exception: ", ex.what() ); } |
|
267 catch( std::domain_error const& ex ) |
|
268 { detail::report_error( execution_exception::cpp_exception_error, "std::domain_error: ", ex.what() ); } |
|
269 catch( std::invalid_argument const& ex ) |
|
270 { detail::report_error( execution_exception::cpp_exception_error, "std::invalid_argument: ", ex.what() ); } |
|
271 catch( std::length_error const& ex ) |
|
272 { detail::report_error( execution_exception::cpp_exception_error, "std::length_error: ", ex.what() ); } |
|
273 catch( std::out_of_range const& ex ) |
|
274 { detail::report_error( execution_exception::cpp_exception_error, "std::out_of_range: ", ex.what() ); } |
|
275 catch( std::range_error const& ex ) |
|
276 { detail::report_error( execution_exception::cpp_exception_error, "std::range_error: ", ex.what() ); } |
|
277 catch( std::overflow_error const& ex ) |
|
278 { detail::report_error( execution_exception::cpp_exception_error, "std::overflow_error: ", ex.what() ); } |
|
279 catch( std::underflow_error const& ex ) |
|
280 { detail::report_error( execution_exception::cpp_exception_error, "std::underflow_error: ", ex.what() ); } |
|
281 catch( std::logic_error const& ex ) |
|
282 { detail::report_error( execution_exception::cpp_exception_error, "std::logic_error: ", ex.what() ); } |
|
283 catch( std::runtime_error const& ex ) |
|
284 { detail::report_error( execution_exception::cpp_exception_error, "std::runtime_error: ", ex.what() ); } |
|
285 catch( std::exception const& ex ) |
|
286 { detail::report_error( execution_exception::cpp_exception_error, "std::exception: ", ex.what() ); } |
|
287 |
|
288 #if defined(BOOST_MS_STRUCTURED_EXCEPTION_HANDLING) |
|
289 catch( detail::ms_se_exception const& ex ) |
|
290 { detail::report_ms_se_error( ex.id() ); } |
|
291 #elif defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING) |
|
292 catch( detail::unix_signal_exception const& ex ) |
|
293 { detail::report_error( ex.error_code(), ex.error_message() ); } |
|
294 #endif // BOOST_SIGACTION_BASED_SIGNAL_HANDLING |
|
295 |
|
296 catch( execution_aborted const& ) |
|
297 { return 0; } |
|
298 |
|
299 catch( execution_exception const& ) |
|
300 { throw; } |
|
301 |
|
302 catch( ... ) |
|
303 { detail::report_error( execution_exception::cpp_exception_error, "unknown type" ); } |
|
304 |
|
305 return 0; // never reached; supplied to quiet compiler warnings |
|
306 } // execute |
|
307 |
|
308 //____________________________________________________________________________// |
|
309 |
|
310 #if defined(BOOST_SIGACTION_BASED_SIGNAL_HANDLING) |
|
311 |
|
312 // ************************************************************************** // |
|
313 // ************** boost::detail::signal_handler ************** // |
|
314 // ************************************************************************** // |
|
315 |
|
316 namespace detail { |
|
317 |
|
318 class signal_handler { |
|
319 public: |
|
320 // Constructor |
|
321 EXPORT_C explicit signal_handler( bool catch_system_errors, int timeout ); |
|
322 |
|
323 // Destructor |
|
324 ~signal_handler(); |
|
325 |
|
326 // access methods |
|
327 static sigjmp_buf& jump_buffer() |
|
328 { |
|
329 assert( !!s_active_handler ); |
|
330 |
|
331 return s_active_handler->m_sigjmp_buf; |
|
332 } |
|
333 |
|
334 private: |
|
335 // Data members |
|
336 struct sigaction m_same_action_for_all_signals; |
|
337 struct sigaction m_old_SIGFPE_action; |
|
338 struct sigaction m_old_SIGTRAP_action; |
|
339 struct sigaction m_old_SIGSEGV_action; |
|
340 struct sigaction m_old_SIGBUS_action; |
|
341 struct sigaction m_old_SIGABRT_action; |
|
342 struct sigaction m_old_SIGALRM_action; |
|
343 |
|
344 sigjmp_buf m_sigjmp_buf; |
|
345 |
|
346 signal_handler* m_prev_handler; |
|
347 static signal_handler* s_active_handler; |
|
348 |
|
349 bool m_catch_system_errors; |
|
350 bool m_set_timeout; |
|
351 }; |
|
352 |
|
353 signal_handler* signal_handler::s_active_handler = NULL; // !! need to be placed in thread specific storage |
|
354 |
|
355 //____________________________________________________________________________// |
|
356 |
|
357 extern "C" { |
|
358 |
|
359 static void execution_monitor_signal_handler( int sig ) |
|
360 { |
|
361 siglongjmp( signal_handler::jump_buffer(), sig ); |
|
362 } |
|
363 |
|
364 } |
|
365 |
|
366 //____________________________________________________________________________// |
|
367 |
|
368 signal_handler::signal_handler( bool catch_system_errors, int timeout ) |
|
369 : m_prev_handler( s_active_handler ) |
|
370 , m_catch_system_errors( catch_system_errors ) |
|
371 , m_set_timeout( timeout > 0 ) |
|
372 { |
|
373 s_active_handler = this; |
|
374 |
|
375 if( m_catch_system_errors || m_set_timeout ) { |
|
376 m_same_action_for_all_signals.sa_flags = 0; |
|
377 m_same_action_for_all_signals.sa_handler = &execution_monitor_signal_handler; |
|
378 sigemptyset( &m_same_action_for_all_signals.sa_mask ); |
|
379 } |
|
380 |
|
381 if( m_catch_system_errors ) { |
|
382 sigaction( SIGFPE , &m_same_action_for_all_signals, &m_old_SIGFPE_action ); |
|
383 sigaction( SIGTRAP, &m_same_action_for_all_signals, &m_old_SIGTRAP_action ); |
|
384 sigaction( SIGSEGV, &m_same_action_for_all_signals, &m_old_SIGSEGV_action ); |
|
385 sigaction( SIGBUS , &m_same_action_for_all_signals, &m_old_SIGBUS_action ); |
|
386 sigaction( SIGABRT, &m_same_action_for_all_signals, &m_old_SIGABRT_action ); |
|
387 } |
|
388 |
|
389 if( m_set_timeout ) { |
|
390 sigaction( SIGALRM , &m_same_action_for_all_signals, &m_old_SIGALRM_action ); |
|
391 alarm( timeout ); |
|
392 } |
|
393 } |
|
394 |
|
395 //____________________________________________________________________________// |
|
396 |
|
397 signal_handler::~signal_handler() |
|
398 { |
|
399 typedef struct sigaction* sigaction_ptr; |
|
400 |
|
401 assert( s_active_handler == this ); |
|
402 |
|
403 if( m_set_timeout ) { |
|
404 alarm( 0 ); |
|
405 sigaction( SIGALRM, &m_old_SIGALRM_action, sigaction_ptr() ); |
|
406 } |
|
407 |
|
408 if( m_catch_system_errors ) { |
|
409 sigaction( SIGFPE , &m_old_SIGFPE_action , sigaction_ptr() ); |
|
410 sigaction( SIGTRAP, &m_old_SIGTRAP_action, sigaction_ptr() ); |
|
411 sigaction( SIGSEGV, &m_old_SIGSEGV_action, sigaction_ptr() ); |
|
412 sigaction( SIGBUS , &m_old_SIGBUS_action , sigaction_ptr() ); |
|
413 sigaction( SIGABRT, &m_old_SIGABRT_action, sigaction_ptr() ); |
|
414 } |
|
415 |
|
416 s_active_handler = m_prev_handler; |
|
417 } |
|
418 |
|
419 //____________________________________________________________________________// |
|
420 |
|
421 } // namespace detail |
|
422 |
|
423 // ************************************************************************** // |
|
424 // ************** execution_monitor::catch_signals ************** // |
|
425 // ************************************************************************** // |
|
426 |
|
427 EXPORT_C int |
|
428 execution_monitor::catch_signals( unit_test::callback0<int> const& F, bool catch_system_errors, int timeout ) |
|
429 { |
|
430 using namespace detail; |
|
431 |
|
432 signal_handler local_signal_handler( catch_system_errors, timeout ); |
|
433 |
|
434 volatile int sigtype = sigsetjmp( signal_handler::jump_buffer(), 1 ); |
|
435 |
|
436 typedef execution_exception::error_code ec_type; |
|
437 int result = 0; |
|
438 ec_type ec = execution_exception::no_error; |
|
439 const_string em; |
|
440 |
|
441 if( sigtype == 0 ) { |
|
442 result = m_custom_translators ? (*m_custom_translators)( F ) : F(); |
|
443 } |
|
444 else { |
|
445 switch(sigtype) { |
|
446 case SIGALRM: |
|
447 ec = execution_exception::timeout_error; |
|
448 em = BOOST_TEST_L( "signal: SIGALRM (timeout while executing function)" ); |
|
449 break; |
|
450 case SIGTRAP: |
|
451 ec = execution_exception::system_error; |
|
452 em = BOOST_TEST_L( "signal: SIGTRAP (perhaps integer divide by zero)" ); |
|
453 break; |
|
454 case SIGFPE: |
|
455 ec = execution_exception::system_error; |
|
456 em = BOOST_TEST_L( "signal: SIGFPE (arithmetic exception)" ); |
|
457 break; |
|
458 case SIGABRT: |
|
459 ec = execution_exception::system_error; |
|
460 em = BOOST_TEST_L( "signal: SIGABRT (application abort requested)" ); |
|
461 break; |
|
462 case SIGSEGV: |
|
463 case SIGBUS: |
|
464 ec = execution_exception::system_fatal_error; |
|
465 em = BOOST_TEST_L( "memory access violation" ); |
|
466 break; |
|
467 default: |
|
468 ec = execution_exception::system_error; |
|
469 em = BOOST_TEST_L( "unrecognized signal" ); |
|
470 } |
|
471 } |
|
472 |
|
473 if( ec != execution_exception::no_error ) |
|
474 throw unix_signal_exception( ec, em ); |
|
475 |
|
476 return result; |
|
477 } // unix catch_signals |
|
478 |
|
479 //____________________________________________________________________________// |
|
480 |
|
481 #elif (defined(__BORLANDC__) && defined(_Windows) && !defined(BOOST_DISABLE_WIN32)) |
|
482 |
|
483 // this works for Borland but not other Win32 compilers (which trap too many cases) |
|
484 EXPORT_C int |
|
485 execution_monitor::catch_signals( unit_test::callback0<int> const& F, bool catch_system_errors, int ) |
|
486 { |
|
487 int result; |
|
488 |
|
489 if( catch_system_errors ) { |
|
490 __try { result = m_custom_translators ? (*m_custom_translators)( F ) : F(); } |
|
491 |
|
492 __except (1) { |
|
493 throw detail::ms_se_exception( GetExceptionCode() ); |
|
494 } |
|
495 } |
|
496 else |
|
497 result = m_custom_translators ? (*m_custom_translators)( F ) : F(); |
|
498 |
|
499 return result; |
|
500 } |
|
501 |
|
502 #else // default signal handler |
|
503 |
|
504 EXPORT_C int |
|
505 execution_monitor::catch_signals( unit_test::callback0<int> const& F, bool, int ) |
|
506 { |
|
507 return m_custom_translators ? (*m_custom_translators)( F ) : F(); |
|
508 } |
|
509 |
|
510 #endif // choose signal handler |
|
511 |
|
512 // ************************************************************************** // |
|
513 // ************** Microsoft structured exception handling ************** // |
|
514 // ************************************************************************** // |
|
515 |
|
516 #if defined(BOOST_MS_STRUCTURED_EXCEPTION_HANDLING) |
|
517 |
|
518 namespace detail { |
|
519 |
|
520 EXPORT_C void |
|
521 ms_se_trans_func( unsigned int id, _EXCEPTION_POINTERS* /* exps */ ) |
|
522 { |
|
523 throw ms_se_exception( id ); |
|
524 } |
|
525 |
|
526 //____________________________________________________________________________// |
|
527 |
|
528 EXPORT_C void |
|
529 ms_se_forward_func( unsigned int /* id */, _EXCEPTION_POINTERS* /* exps */ ) |
|
530 { |
|
531 throw; |
|
532 } |
|
533 |
|
534 //____________________________________________________________________________// |
|
535 |
|
536 EXPORT_C void |
|
537 report_ms_se_error( unsigned int id ) |
|
538 { |
|
539 switch( id ) { |
|
540 // cases classified as fatal_system_error |
|
541 case EXCEPTION_ACCESS_VIOLATION: |
|
542 detail::report_error( execution_exception::system_fatal_error, "memory access violation" ); |
|
543 break; |
|
544 |
|
545 case EXCEPTION_ILLEGAL_INSTRUCTION: |
|
546 detail::report_error( execution_exception::system_fatal_error, "illegal instruction" ); |
|
547 break; |
|
548 |
|
549 case EXCEPTION_PRIV_INSTRUCTION: |
|
550 detail::report_error( execution_exception::system_fatal_error, "privileged instruction" ); |
|
551 break; |
|
552 |
|
553 case EXCEPTION_IN_PAGE_ERROR: |
|
554 detail::report_error( execution_exception::system_fatal_error, "memory page error" ); |
|
555 break; |
|
556 |
|
557 case EXCEPTION_STACK_OVERFLOW: |
|
558 detail::report_error( execution_exception::system_fatal_error, "stack overflow" ); |
|
559 break; |
|
560 |
|
561 // cases classified as (non-fatal) system_trap |
|
562 case EXCEPTION_DATATYPE_MISALIGNMENT: |
|
563 detail::report_error( execution_exception::system_error, "data misalignment" ); |
|
564 break; |
|
565 |
|
566 case EXCEPTION_INT_DIVIDE_BY_ZERO: |
|
567 detail::report_error( execution_exception::system_error, "integer divide by zero" ); |
|
568 break; |
|
569 |
|
570 case EXCEPTION_INT_OVERFLOW: |
|
571 detail::report_error( execution_exception::system_error, "integer overflow" ); |
|
572 break; |
|
573 |
|
574 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: |
|
575 detail::report_error( execution_exception::system_error, "array bounds exceeded" ); |
|
576 break; |
|
577 |
|
578 case EXCEPTION_FLT_DIVIDE_BY_ZERO: |
|
579 detail::report_error( execution_exception::system_error, "floating point divide by zero" ); |
|
580 break; |
|
581 |
|
582 case EXCEPTION_FLT_STACK_CHECK: |
|
583 detail::report_error( execution_exception::system_error, "floating point stack check" ); |
|
584 break; |
|
585 |
|
586 case EXCEPTION_FLT_DENORMAL_OPERAND: |
|
587 case EXCEPTION_FLT_INEXACT_RESULT: |
|
588 case EXCEPTION_FLT_INVALID_OPERATION: |
|
589 case EXCEPTION_FLT_OVERFLOW: |
|
590 case EXCEPTION_FLT_UNDERFLOW: |
|
591 detail::report_error( execution_exception::system_error, "floating point error" ); |
|
592 break; |
|
593 |
|
594 default: |
|
595 detail::report_error( execution_exception::system_error, "unrecognized exception or signal" ); |
|
596 break; |
|
597 } // switch |
|
598 } // report_ms_se_error |
|
599 |
|
600 //____________________________________________________________________________// |
|
601 |
|
602 } // namespace detail |
|
603 |
|
604 #endif // Microsoft structured exception handling |
|
605 |
|
606 // ************************************************************************** // |
|
607 // ************** report_error ************** // |
|
608 // ************************************************************************** // |
|
609 |
|
610 namespace detail { |
|
611 |
|
612 static void report_error( execution_exception::error_code ec, const_string msg1, const_string msg2 ) |
|
613 { |
|
614 static char buf[REPORT_ERROR_BUFFER_SIZE]; |
|
615 |
|
616 buf[0] = '\0'; |
|
617 |
|
618 std::strncat( buf, msg1.begin(), sizeof(buf)-1 ); |
|
619 std::strncat( buf, msg2.begin(), sizeof(buf) - msg1.size() - 1 ); |
|
620 |
|
621 throw execution_exception( ec, buf ); |
|
622 } |
|
623 |
|
624 //____________________________________________________________________________// |
|
625 |
|
626 } // namespace detail |
|
627 |
|
628 // ************************************************************************** // |
|
629 // ************** detect_memory_leaks ************** // |
|
630 // ************************************************************************** // |
|
631 |
|
632 EXPORT_C void |
|
633 detect_memory_leaks( bool on_off ) |
|
634 { |
|
635 unit_test::ut_detail::ignore_unused_variable_warning( on_off ); |
|
636 |
|
637 #ifdef BOOST_MS_CRT_DEBUG_HOOKS |
|
638 int flags = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ); |
|
639 |
|
640 if( !on_off ) |
|
641 flags &= ~_CRTDBG_LEAK_CHECK_DF; |
|
642 else { |
|
643 flags |= _CRTDBG_LEAK_CHECK_DF; |
|
644 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); |
|
645 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT); |
|
646 } |
|
647 |
|
648 _CrtSetDbgFlag ( flags ); |
|
649 #endif // BOOST_MS_CRT_DEBUG_HOOKS |
|
650 } |
|
651 |
|
652 //____________________________________________________________________________// |
|
653 |
|
654 EXPORT_C void |
|
655 break_memory_alloc( long mem_alloc_order_num ) |
|
656 { |
|
657 unit_test::ut_detail::ignore_unused_variable_warning( mem_alloc_order_num ); |
|
658 |
|
659 #ifdef BOOST_MS_CRT_DEBUG_HOOKS |
|
660 _CrtSetBreakAlloc( mem_alloc_order_num ); |
|
661 #endif // BOOST_MS_CRT_DEBUG_HOOKS |
|
662 } |
|
663 |
|
664 } // namespace boost |
|
665 |
|
666 //____________________________________________________________________________// |
|
667 |
|
668 #include <boost/test/detail/enable_warnings.hpp> |
|
669 |
|
670 // *************************************************************************** |
|
671 // Revision History : |
|
672 // |
|
673 // $Log: execution_monitor.ipp,v $ |
|
674 // Revision 1.13 2006/02/22 16:14:45 rogeeff |
|
675 // reagance to eliminate warning |
|
676 // |
|
677 // Revision 1.12 2006/01/30 07:29:49 rogeeff |
|
678 // split memory leaks detection API in two to get more functions with better defined roles |
|
679 // |
|
680 // Revision 1.11 2006/01/15 09:47:43 rogeeff |
|
681 // make common message |
|
682 // |
|
683 // Revision 1.10 2005/12/14 05:52:49 rogeeff |
|
684 // *** empty log message *** |
|
685 // |
|
686 // Revision 1.9 2005/04/30 17:07:22 rogeeff |
|
687 // ignore_warning included |
|
688 // |
|
689 // Revision 1.8 2005/04/30 16:46:50 rogeeff |
|
690 // warning suppressed |
|
691 // |
|
692 // Revision 1.7 2005/04/13 05:32:03 rogeeff |
|
693 // typo fix |
|
694 // |
|
695 // Revision 1.6 2005/04/05 06:11:37 rogeeff |
|
696 // memory leak allocation point detection\nextra help with _WIN32_WINNT |
|
697 // |
|
698 // Revision 1.5 2005/02/20 08:27:07 rogeeff |
|
699 // This a major update for Boost.Test framework. See release docs for complete list of fixes/updates |
|
700 // |
|
701 // Revision 1.4 2005/02/01 06:40:07 rogeeff |
|
702 // copyright update |
|
703 // old log entries removed |
|
704 // minor stilistic changes |
|
705 // depricated tools removed |
|
706 // |
|
707 // Revision 1.3 2005/01/31 07:50:06 rogeeff |
|
708 // cdecl portability fix |
|
709 // |
|
710 // Revision 1.2 2005/01/31 05:58:03 rogeeff |
|
711 // detect_memory_leak feature added |
|
712 // |
|
713 // Revision 1.1 2005/01/22 19:22:12 rogeeff |
|
714 // implementation moved into headers section to eliminate dependency of included/minimal component on src directory |
|
715 // |
|
716 // Revision 1.36 2005/01/21 07:21:38 rogeeff |
|
717 // detect presence of debugger under VC and automatically prevent catching system errors |
|
718 // |
|
719 // *************************************************************************** |
|
720 |
|
721 #endif // BOOST_TEST_EXECUTION_MONITOR_IPP_012205GER |