1 /*
2  *  Created by Phil on 21/08/2014
3  *  Copyright 2014 Two Blue Cubes Ltd. All rights reserved.
4  *
5  *  Distributed under the Boost Software License, Version 1.0. (See accompanying
6  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  *
8  */
9 #ifndef TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
10 #define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
11 
12 #include "catch_platform.h"
13 #include "catch_compiler_capabilities.h"
14 
15 #include <cassert>
16 
17 namespace Catch {
18 
19     // Wrapper for platform-specific fatal error (signals/SEH) handlers
20     //
21     // Tries to be cooperative with other handlers, and not step over
22     // other handlers. This means that unknown structured exceptions
23     // are passed on, previous signal handlers are called, and so on.
24     //
25     // Can only be instantiated once, and assumes that once a signal
26     // is caught, the binary will end up terminating. Thus, there
27     class FatalConditionHandler {
28         bool m_started = false;
29 
30         // Install/disengage implementation for specific platform.
31         // Should be if-defed to work on current platform, can assume
32         // engage-disengage 1:1 pairing.
33         void engage_platform();
34         void disengage_platform();
35     public:
36         // Should also have platform-specific implementations as needed
37         FatalConditionHandler();
38         ~FatalConditionHandler();
39 
engage()40         void engage() {
41             assert(!m_started && "Handler cannot be installed twice.");
42             m_started = true;
43             engage_platform();
44         }
45 
disengage()46         void disengage() {
47             assert(m_started && "Handler cannot be uninstalled without being installed first");
48             m_started = false;
49             disengage_platform();
50         }
51     };
52 
53     //! Simple RAII guard for (dis)engaging the FatalConditionHandler
54     class FatalConditionHandlerGuard {
55         FatalConditionHandler* m_handler;
56     public:
FatalConditionHandlerGuard(FatalConditionHandler * handler)57         FatalConditionHandlerGuard(FatalConditionHandler* handler):
58             m_handler(handler) {
59             m_handler->engage();
60         }
~FatalConditionHandlerGuard()61         ~FatalConditionHandlerGuard() {
62             m_handler->disengage();
63         }
64     };
65 
66 } // end namespace Catch
67 
68 #endif // TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
69