summaryrefslogtreecommitdiffstats
path: root/lib/base/exception.hpp
blob: 18dab650e6e6c406361644138d1f42fe6089499e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */

#ifndef EXCEPTION_H
#define EXCEPTION_H

#include "base/i2-base.hpp"
#include "base/string.hpp"
#include "base/context.hpp"
#include "base/debuginfo.hpp"
#include "base/dictionary.hpp"
#include "base/configobject.hpp"
#include <boost/exception/errinfo_api_function.hpp>
#include <boost/exception/errinfo_errno.hpp>
#include <boost/exception/errinfo_file_name.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <boost/exception_ptr.hpp>
#include <boost/stacktrace.hpp>

#ifdef _WIN32
#	include <boost/algorithm/string/trim.hpp>
#endif /* _WIN32 */

namespace icinga
{

class user_error : virtual public std::exception, virtual public boost::exception
{ };

/*
 * @ingroup base
 */
class ScriptError : virtual public user_error
{
public:
	ScriptError(String message);
	ScriptError(String message, DebugInfo di, bool incompleteExpr = false);

	const char *what(void) const throw() final;

	DebugInfo GetDebugInfo() const;
	bool IsIncompleteExpression() const;

	bool IsHandledByDebugger() const;
	void SetHandledByDebugger(bool handled);

private:
	String m_Message;
	DebugInfo m_DebugInfo;
	bool m_IncompleteExpr;
	bool m_HandledByDebugger;
};

/*
 * @ingroup base
 */
class ValidationError : virtual public user_error
{
public:
	ValidationError(const ConfigObject::Ptr& object, const std::vector<String>& attributePath, const String& message);
	~ValidationError() throw() override;

	const char *what() const throw() override;

	ConfigObject::Ptr GetObject() const;
	std::vector<String> GetAttributePath() const;
	String GetMessage() const;

	void SetDebugHint(const Dictionary::Ptr& dhint);
	Dictionary::Ptr GetDebugHint() const;

private:
	ConfigObject::Ptr m_Object;
	std::vector<String> m_AttributePath;
	String m_Message;
	String m_What;
	Dictionary::Ptr m_DebugHint;
};

boost::stacktrace::stacktrace *GetLastExceptionStack();
void SetLastExceptionStack(const boost::stacktrace::stacktrace& trace);

ContextTrace *GetLastExceptionContext();
void SetLastExceptionContext(const ContextTrace& context);

void RethrowUncaughtException();

struct errinfo_stacktrace_;
typedef boost::error_info<struct errinfo_stacktrace_, boost::stacktrace::stacktrace> StackTraceErrorInfo;

std::string to_string(const StackTraceErrorInfo&);

typedef boost::error_info<ContextTrace, ContextTrace> ContextTraceErrorInfo;

std::string to_string(const ContextTraceErrorInfo& e);

/**
 * Generate diagnostic information about an exception
 *
 * The following information is gathered in the result:
 *  - Exception error message
 *  - Debug information about the Icinga config if the exception is a ValidationError
 *  - Stack trace
 *  - Context trace
 *
 *  Each, stack trace and the context trace, are printed if the they were saved in the boost exception error
 *  information, are explicitly passed as a parameter, or were stored when the last exception was thrown. If multiple
 *  of these exist, the first one is used.
 *
 * @param ex exception to print diagnostic information about
 * @param verbose if verbose is set, a stack trace is added
 * @param stack optionally supply a stack trace
 * @param context optionally supply a context trace
 * @return string containing the aforementioned information
 */
String DiagnosticInformation(const std::exception& ex, bool verbose = true,
	boost::stacktrace::stacktrace *stack = nullptr, ContextTrace *context = nullptr);
String DiagnosticInformation(const boost::exception_ptr& eptr, bool verbose = true);

class posix_error : virtual public std::exception, virtual public boost::exception {
public:
	~posix_error() throw() override;

	const char *what(void) const throw() final;

private:
	mutable char *m_Message{nullptr};
};

#ifdef _WIN32
class win32_error : virtual public std::exception, virtual public boost::exception {
public:
	const char *what() const noexcept override;
};

std::string to_string(const win32_error& e);

struct errinfo_win32_error_;
typedef boost::error_info<struct errinfo_win32_error_, int> errinfo_win32_error;

std::string to_string(const errinfo_win32_error& e);
#endif /* _WIN32 */

struct errinfo_getaddrinfo_error_;
typedef boost::error_info<struct errinfo_getaddrinfo_error_, int> errinfo_getaddrinfo_error;

std::string to_string(const errinfo_getaddrinfo_error& e);

struct errinfo_message_;
typedef boost::error_info<struct errinfo_message_, std::string> errinfo_message;

class invalid_downtime_removal_error : virtual public std::exception, virtual public boost::exception {
public:
	explicit invalid_downtime_removal_error(String message);
	explicit invalid_downtime_removal_error(const char* message);

	~invalid_downtime_removal_error() noexcept override;

	const char *what() const noexcept final;

private:
	String m_Message;
};

}

#endif /* EXCEPTION_H */