340231734d3620b113f622ab7879c7b1bac5bae2
[lttng-tools.git] / src / common / exception.hpp
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
11 #include <common/string-utils/c-string-view.hpp>
12
13 #include <lttng/lttng-error.h>
14
15 #include <stdexcept>
16 #include <string>
17 #include <system_error>
18
19 #define LTTNG_SOURCE_LOCATION() lttng::source_location(__FILE__, __func__, __LINE__)
20
21 #define LTTNG_THROW_CTL(msg, error_code) \
22 throw lttng::ctl::error(msg, error_code, LTTNG_SOURCE_LOCATION())
23 #define LTTNG_THROW_POSIX(msg, errno_code) \
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())
26 #define LTTNG_THROW_ALLOCATION_FAILURE_ERROR(msg, allocation_size) \
27 throw lttng::allocation_failure(msg, allocation_size, LTTNG_SOURCE_LOCATION())
28 #define LTTNG_THROW_UNSUPPORTED_ERROR(msg) \
29 throw lttng::unsupported_error(msg, LTTNG_SOURCE_LOCATION())
30 #define LTTNG_THROW_COMMUNICATION_ERROR(msg) \
31 throw lttng::communication_error(msg, LTTNG_SOURCE_LOCATION())
32 #define LTTNG_THROW_PROTOCOL_ERROR(msg) throw lttng::protocol_error(msg, LTTNG_SOURCE_LOCATION())
33 #define LTTNG_THROW_INVALID_ARGUMENT_ERROR(msg) \
34 throw lttng::invalid_argument_error(msg, LTTNG_SOURCE_LOCATION())
35
36 namespace lttng {
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 */
90 class runtime_error : public std::runtime_error {
91 public:
92 runtime_error(const std::string& msg, const lttng::source_location& source_location);
93
94 lttng::source_location source_location;
95 };
96
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
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 {
121 public:
122 explicit unsupported_error(const std::string& msg,
123 const lttng::source_location& source_location);
124 };
125
126 namespace ctl {
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 */
135 class error : public runtime_error {
136 public:
137 explicit error(const std::string& msg,
138 lttng_error_code error_code,
139 const lttng::source_location& source_location);
140
141 lttng_error_code code() const noexcept
142 {
143 return _error_code;
144 }
145
146 private:
147 const lttng_error_code _error_code;
148 };
149 } /* namespace ctl */
150
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 {
156 public:
157 explicit posix_error(const std::string& msg,
158 unsigned int errno_code,
159 const lttng::source_location& source_location);
160 };
161
162 /**
163 * @class communication_error
164 * @brief Base class for communication errors between components.
165 */
166 class communication_error : public lttng::runtime_error {
167 public:
168 explicit communication_error(const std::string& msg,
169 const lttng::source_location& source_location);
170 };
171
172 /**
173 * @class protocol_error
174 * @brief Base class for protocol layer communication errors (encoding or decoding problems).
175 */
176 class protocol_error : public communication_error {
177 public:
178 explicit protocol_error(const std::string& msg,
179 const lttng::source_location& source_location);
180 };
181
182 /**
183 * @class invalid_argument_error
184 * @brief Represents an error for invalid arguments.
185 */
186 class invalid_argument_error : public lttng::runtime_error {
187 public:
188 explicit invalid_argument_error(const std::string& msg,
189 const lttng::source_location& source_location);
190 };
191
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 */
215
216 #endif /* LTTNG_EXCEPTION_H_ */
This page took 0.033244 seconds and 3 git commands to generate.