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