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