1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2 
3 #ifndef EXCEPTION_H
4 #define EXCEPTION_H
5 
6 #include "base/i2-base.hpp"
7 #include "base/string.hpp"
8 #include "base/context.hpp"
9 #include "base/debuginfo.hpp"
10 #include "base/dictionary.hpp"
11 #include "base/configobject.hpp"
12 #include <boost/exception/errinfo_api_function.hpp>
13 #include <boost/exception/errinfo_errno.hpp>
14 #include <boost/exception/errinfo_file_name.hpp>
15 #include <boost/exception/diagnostic_information.hpp>
16 #include <boost/exception_ptr.hpp>
17 #include <boost/stacktrace.hpp>
18 
19 #ifdef _WIN32
20 #	include <boost/algorithm/string/trim.hpp>
21 #endif /* _WIN32 */
22 
23 namespace icinga
24 {
25 
26 class user_error : virtual public std::exception, virtual public boost::exception
27 { };
28 
29 /*
30  * @ingroup base
31  */
32 class ScriptError : virtual public user_error
33 {
34 public:
35 	ScriptError(String message);
36 	ScriptError(String message, DebugInfo di, bool incompleteExpr = false);
37 
38 	const char *what(void) const throw() final;
39 
40 	DebugInfo GetDebugInfo() const;
41 	bool IsIncompleteExpression() const;
42 
43 	bool IsHandledByDebugger() const;
44 	void SetHandledByDebugger(bool handled);
45 
46 private:
47 	String m_Message;
48 	DebugInfo m_DebugInfo;
49 	bool m_IncompleteExpr;
50 	bool m_HandledByDebugger;
51 };
52 
53 /*
54  * @ingroup base
55  */
56 class ValidationError : virtual public user_error
57 {
58 public:
59 	ValidationError(const ConfigObject::Ptr& object, const std::vector<String>& attributePath, const String& message);
60 	~ValidationError() throw() override;
61 
62 	const char *what() const throw() override;
63 
64 	ConfigObject::Ptr GetObject() const;
65 	std::vector<String> GetAttributePath() const;
66 	String GetMessage() const;
67 
68 	void SetDebugHint(const Dictionary::Ptr& dhint);
69 	Dictionary::Ptr GetDebugHint() const;
70 
71 private:
72 	ConfigObject::Ptr m_Object;
73 	std::vector<String> m_AttributePath;
74 	String m_Message;
75 	String m_What;
76 	Dictionary::Ptr m_DebugHint;
77 };
78 
79 boost::stacktrace::stacktrace *GetLastExceptionStack();
80 void SetLastExceptionStack(const boost::stacktrace::stacktrace& trace);
81 
82 ContextTrace *GetLastExceptionContext();
83 void SetLastExceptionContext(const ContextTrace& context);
84 
85 void RethrowUncaughtException();
86 
87 struct errinfo_stacktrace_;
88 typedef boost::error_info<struct errinfo_stacktrace_, boost::stacktrace::stacktrace> StackTraceErrorInfo;
89 
90 std::string to_string(const StackTraceErrorInfo&);
91 
92 typedef boost::error_info<ContextTrace, ContextTrace> ContextTraceErrorInfo;
93 
94 std::string to_string(const ContextTraceErrorInfo& e);
95 
96 /**
97  * Generate diagnostic information about an exception
98  *
99  * The following information is gathered in the result:
100  *  - Exception error message
101  *  - Debug information about the Icinga config if the exception is a ValidationError
102  *  - Stack trace
103  *  - Context trace
104  *
105  *  Each, stack trace and the context trace, are printed if the they were saved in the boost exception error
106  *  information, are explicitly passed as a parameter, or were stored when the last exception was thrown. If multiple
107  *  of these exist, the first one is used.
108  *
109  * @param ex exception to print diagnostic information about
110  * @param verbose if verbose is set, a stack trace is added
111  * @param stack optionally supply a stack trace
112  * @param context optionally supply a context trace
113  * @return string containing the aforementioned information
114  */
115 String DiagnosticInformation(const std::exception& ex, bool verbose = true,
116 	boost::stacktrace::stacktrace *stack = nullptr, ContextTrace *context = nullptr);
117 String DiagnosticInformation(const boost::exception_ptr& eptr, bool verbose = true);
118 
119 class posix_error : virtual public std::exception, virtual public boost::exception {
120 public:
121 	~posix_error() throw() override;
122 
123 	const char *what(void) const throw() final;
124 
125 private:
126 	mutable char *m_Message{nullptr};
127 };
128 
129 #ifdef _WIN32
130 class win32_error : virtual public std::exception, virtual public boost::exception { };
131 
132 struct errinfo_win32_error_;
133 typedef boost::error_info<struct errinfo_win32_error_, int> errinfo_win32_error;
134 
135 std::string to_string(const errinfo_win32_error& e);
136 #endif /* _WIN32 */
137 
138 struct errinfo_getaddrinfo_error_;
139 typedef boost::error_info<struct errinfo_getaddrinfo_error_, int> errinfo_getaddrinfo_error;
140 
141 std::string to_string(const errinfo_getaddrinfo_error& e);
142 
143 struct errinfo_message_;
144 typedef boost::error_info<struct errinfo_message_, std::string> errinfo_message;
145 
146 class invalid_downtime_removal_error : virtual public std::exception, virtual public boost::exception {
147 public:
148 	explicit invalid_downtime_removal_error(String message);
149 	explicit invalid_downtime_removal_error(const char* message);
150 
151 	~invalid_downtime_removal_error() noexcept override;
152 
153 	const char *what() const noexcept final;
154 
155 private:
156 	String m_Message;
157 };
158 
159 }
160 
161 #endif /* EXCEPTION_H */
162