Commit | Line | Data |
---|---|---|
53cd1e22 JG |
1 | /* |
2 | * Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com> | |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
5 | * | |
6 | */ | |
7 | ||
8 | #ifndef LTTNG_EXCEPTION_H_ | |
9 | #define LTTNG_EXCEPTION_H_ | |
10 | ||
9f4d1ef3 JG |
11 | #include <common/string-utils/c-string-view.hpp> |
12 | ||
28f23191 JG |
13 | #include <lttng/lttng-error.h> |
14 | ||
53cd1e22 | 15 | #include <stdexcept> |
28f23191 | 16 | #include <string> |
53cd1e22 JG |
17 | #include <system_error> |
18 | ||
9f4d1ef3 JG |
19 | #define LTTNG_SOURCE_LOCATION() lttng::source_location(__FILE__, __func__, __LINE__) |
20 | ||
0038180d | 21 | #define LTTNG_THROW_CTL(msg, error_code) \ |
9f4d1ef3 | 22 | throw lttng::ctl::error(msg, error_code, LTTNG_SOURCE_LOCATION()) |
53cd1e22 | 23 | #define LTTNG_THROW_POSIX(msg, errno_code) \ |
9f4d1ef3 | 24 | throw lttng::posix_error(msg, errno_code, LTTNG_SOURCE_LOCATION()) |
16d64977 JG |
25 | #define LTTNG_THROW_ERROR(msg) throw lttng::runtime_error(msg, LTTNG_SOURCE_LOCATION()) |
26 | #define LTTNG_THROW_OUT_OF_RANGE(msg) throw lttng::out_of_range(msg, LTTNG_SOURCE_LOCATION()) | |
d9a970b7 JG |
27 | #define LTTNG_THROW_ALLOCATION_FAILURE_ERROR(msg, allocation_size) \ |
28 | throw lttng::allocation_failure(msg, allocation_size, LTTNG_SOURCE_LOCATION()) | |
b6bbb1d6 | 29 | #define LTTNG_THROW_UNSUPPORTED_ERROR(msg) \ |
9f4d1ef3 | 30 | throw lttng::unsupported_error(msg, LTTNG_SOURCE_LOCATION()) |
baac5795 | 31 | #define LTTNG_THROW_COMMUNICATION_ERROR(msg) \ |
9f4d1ef3 JG |
32 | throw lttng::communication_error(msg, LTTNG_SOURCE_LOCATION()) |
33 | #define LTTNG_THROW_PROTOCOL_ERROR(msg) throw lttng::protocol_error(msg, LTTNG_SOURCE_LOCATION()) | |
baac5795 | 34 | #define LTTNG_THROW_INVALID_ARGUMENT_ERROR(msg) \ |
9f4d1ef3 | 35 | throw lttng::invalid_argument_error(msg, LTTNG_SOURCE_LOCATION()) |
53cd1e22 JG |
36 | |
37 | namespace lttng { | |
9f4d1ef3 JG |
38 | /** |
39 | * @class source_location | |
40 | * @brief Represents the location in the source code where an exception was thrown. | |
41 | * | |
42 | * The source_location class captures the file name, function name, and line number | |
43 | * of the source code where an exception occurs. This information is useful for | |
44 | * debugging and logging purposes. | |
45 | * | |
46 | * @details | |
47 | * This class provides: | |
48 | * - The name of the source file (file_name). | |
49 | * - The name of the function (function_name). | |
50 | * - The line number in the source file (line_number). | |
51 | * | |
52 | * Example usage: | |
53 | * @code | |
54 | * try { | |
55 | * // Code that may throw an exception. | |
56 | * } catch (const lttng::runtime_error& ex) { | |
57 | * // Handle the exception, possibly logging location information. | |
58 | * ERR_FMT("{} [{}]", ex.what(), ex.source_location); | |
59 | * } | |
60 | * @endcode | |
61 | */ | |
62 | class source_location { | |
63 | public: | |
64 | source_location(lttng::c_string_view file_name_, | |
65 | lttng::c_string_view function_name_, | |
66 | unsigned int line_number_) : | |
67 | file_name(file_name_), function_name(function_name_), line_number(line_number_) | |
68 | { | |
69 | } | |
70 | ||
71 | lttng::c_string_view file_name; | |
72 | lttng::c_string_view function_name; | |
73 | unsigned int line_number; | |
74 | }; | |
75 | ||
76 | /** | |
77 | * @class runtime_error | |
78 | * @brief Base type for all LTTng exceptions. | |
79 | * | |
80 | * Exceptions in the project provide an error message (through the usual what() method), but that | |
81 | * message may not include the whole context of the error. For example, it is not always desirable | |
82 | * to include the source location in a user-facing message. | |
83 | * | |
84 | * As such, exception handlers should mind the type of the exception being thrown and consider | |
85 | * what context is suitable to extract (e.g. some context may only be relevant at the DEBUG logging | |
86 | * level, while the error message may be user-facing). | |
87 | * | |
88 | * Since 'what()' is marked as noexcept, derived classes should format their generic message during | |
89 | * their construction and pass it to the runtime_error constructor. | |
90 | */ | |
baac5795 JG |
91 | class runtime_error : public std::runtime_error { |
92 | public: | |
9f4d1ef3 JG |
93 | runtime_error(const std::string& msg, const lttng::source_location& source_location); |
94 | ||
95 | lttng::source_location source_location; | |
baac5795 | 96 | }; |
53cd1e22 | 97 | |
d9a970b7 JG |
98 | /** |
99 | * @class allocation_failure | |
100 | * @brief Represents an allocation failure. | |
101 | * | |
102 | * Thrown when an allocation fails. Differs from bad_alloc in that it offers a message and a | |
103 | * source location. | |
104 | */ | |
105 | class allocation_failure : public lttng::runtime_error { | |
106 | public: | |
107 | explicit allocation_failure(const std::string& msg, | |
108 | std::size_t allocation_size, | |
109 | const lttng::source_location& source_location); | |
110 | ||
111 | std::size_t allocation_size; | |
112 | }; | |
113 | ||
16d64977 JG |
114 | /** |
115 | * @class out_of_range | |
116 | * @brief Represents an out of range access error. | |
117 | * | |
118 | * Thrown when attempting to access a container out of its valid range (e.g., advancing an iterator | |
119 | * past end()). | |
120 | */ | |
121 | class out_of_range : public lttng::runtime_error { | |
122 | public: | |
123 | explicit out_of_range(const std::string& msg, | |
124 | const lttng::source_location& source_location); | |
125 | }; | |
126 | ||
9f4d1ef3 JG |
127 | /** |
128 | * @class unsupported_error | |
129 | * @brief Represents an error for unsupported features. | |
130 | * | |
131 | * This error may occur due to the current configuration making a feature unavailable | |
132 | * (e.g. when using an older kernel or tracer release). | |
133 | */ | |
134 | class unsupported_error : public lttng::runtime_error { | |
b6bbb1d6 JG |
135 | public: |
136 | explicit unsupported_error(const std::string& msg, | |
9f4d1ef3 | 137 | const lttng::source_location& source_location); |
b6bbb1d6 JG |
138 | }; |
139 | ||
53cd1e22 | 140 | namespace ctl { |
9f4d1ef3 JG |
141 | /** |
142 | * @class error | |
143 | * @brief Wraps lttng_error_code errors for reporting through liblttng-ctl's interface. | |
144 | * | |
145 | * There is typically a better way to report errors than using this type of exception. However, it | |
146 | * is sometimes useful to transition legacy code to use RAII facilities and exceptions without | |
147 | * revisiting every caller. | |
148 | */ | |
baac5795 | 149 | class error : public runtime_error { |
53cd1e22 | 150 | public: |
0038180d JG |
151 | explicit error(const std::string& msg, |
152 | lttng_error_code error_code, | |
9f4d1ef3 | 153 | const lttng::source_location& source_location); |
20f5a9ae JG |
154 | |
155 | lttng_error_code code() const noexcept | |
156 | { | |
157 | return _error_code; | |
158 | } | |
53cd1e22 JG |
159 | |
160 | private: | |
20f5a9ae | 161 | const lttng_error_code _error_code; |
53cd1e22 JG |
162 | }; |
163 | } /* namespace ctl */ | |
164 | ||
9f4d1ef3 JG |
165 | /** |
166 | * @class posix_error | |
167 | * @brief Wraps a POSIX system error, including the location where the error occurred. | |
168 | */ | |
169 | class posix_error : public std::system_error, lttng::runtime_error { | |
53cd1e22 | 170 | public: |
baac5795 | 171 | explicit posix_error(const std::string& msg, |
9f4d1ef3 JG |
172 | unsigned int errno_code, |
173 | const lttng::source_location& source_location); | |
53cd1e22 JG |
174 | }; |
175 | ||
9f4d1ef3 JG |
176 | /** |
177 | * @class communication_error | |
178 | * @brief Base class for communication errors between components. | |
179 | */ | |
180 | class communication_error : public lttng::runtime_error { | |
baac5795 JG |
181 | public: |
182 | explicit communication_error(const std::string& msg, | |
9f4d1ef3 | 183 | const lttng::source_location& source_location); |
baac5795 JG |
184 | }; |
185 | ||
9f4d1ef3 JG |
186 | /** |
187 | * @class protocol_error | |
188 | * @brief Base class for protocol layer communication errors (encoding or decoding problems). | |
189 | */ | |
baac5795 JG |
190 | class protocol_error : public communication_error { |
191 | public: | |
192 | explicit protocol_error(const std::string& msg, | |
9f4d1ef3 | 193 | const lttng::source_location& source_location); |
baac5795 JG |
194 | }; |
195 | ||
9f4d1ef3 JG |
196 | /** |
197 | * @class invalid_argument_error | |
198 | * @brief Represents an error for invalid arguments. | |
199 | */ | |
200 | class invalid_argument_error : public lttng::runtime_error { | |
aeeb48c6 | 201 | public: |
baac5795 | 202 | explicit invalid_argument_error(const std::string& msg, |
9f4d1ef3 | 203 | const lttng::source_location& source_location); |
aeeb48c6 JG |
204 | }; |
205 | ||
9f4d1ef3 JG |
206 | } /* namespace lttng */ |
207 | ||
208 | /* | |
209 | * Specialize fmt::formatter for lttng::source_location | |
210 | * | |
211 | * Due to a bug in g++ < 7.1, this specialization must be enclosed in the fmt namespace, | |
212 | * see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480. | |
213 | */ | |
214 | namespace fmt { | |
215 | template <> | |
216 | struct formatter<lttng::source_location> : formatter<std::string> { | |
217 | template <typename FormatContextType> | |
218 | typename FormatContextType::iterator format(const lttng::source_location& location, | |
bd9231e4 | 219 | FormatContextType& ctx) const |
9f4d1ef3 JG |
220 | { |
221 | return format_to(ctx.out(), | |
222 | "{}() {}:{}", | |
223 | location.function_name.data(), | |
224 | location.file_name.data(), | |
225 | location.line_number); | |
226 | } | |
227 | }; | |
228 | } /* namespace fmt */ | |
53cd1e22 JG |
229 | |
230 | #endif /* LTTNG_EXCEPTION_H_ */ |