error.hpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #pragma once
7 
8 #include <cudf/errc.hpp>
9 #include <cudf/utilities/export.hpp>
10 
11 #include <cuda.h>
12 #include <cuda_runtime_api.h>
13 
14 #include <stdexcept>
15 #include <string>
16 #include <type_traits>
17 
23 namespace CUDF_EXPORT cudf {
35 struct logic_error : std::logic_error {
41  explicit logic_error(char const* const message) : std::logic_error(message) {}
42 
48  explicit logic_error(std::string const& message) : std::logic_error(message) {}
49 
50  // TODO Add an error code member? This would be useful for translating an
51  // exception to an error code in a pure-C API
52 
53  ~logic_error() override
54  {
55  // Needed so that the first instance of the implicit destructor for any TU isn't 'constructed'
56  // from a host+device function marking the implicit version also as host+device
57  }
58 };
63 struct cuda_error : std::runtime_error {
70  explicit cuda_error(std::string const& message, cudaError_t const& error)
71  : std::runtime_error(message), _cudaError(error)
72  {
73  }
74 
80  [[nodiscard]] cudaError_t error_code() const { return _cudaError; }
81 
82  protected:
83  cudaError_t _cudaError;
84 };
85 
87  using cuda_error::cuda_error; // Inherit constructors
88 };
89 
97 struct data_type_error : std::invalid_argument {
103  explicit data_type_error(char const* const message) : std::invalid_argument(message) {}
104 
110  explicit data_type_error(std::string const& message) : std::invalid_argument(message) {}
111 };
112 
118 struct evaluation_error : public std::exception {
125  evaluation_error(errc error, std::string message) : error_(error), message_(std::move(message)) {}
126 
131  [[nodiscard]] char const* what() const noexcept override { return message_.c_str(); }
132 
137  [[nodiscard]] errc error_code() const { return error_; }
138 
139  private:
140  errc error_; //< The error code that occurred during evaluation
141  std::string message_; //< An error message describing the evaluation error
142 };
143 
146 } // namespace CUDF_EXPORT cudf
147 
148 #define STRINGIFY_DETAIL(x) #x
149 #define CUDF_STRINGIFY(x) STRINGIFY_DETAIL(x)
150 
182 #define CUDF_EXPECTS(...) \
183  GET_CUDF_EXPECTS_MACRO(__VA_ARGS__, CUDF_EXPECTS_3, CUDF_EXPECTS_2) \
184  (__VA_ARGS__)
185 
187 
188 #define GET_CUDF_EXPECTS_MACRO(_1, _2, _3, NAME, ...) NAME
189 
190 #define CUDF_EXPECTS_3(_condition, _reason, _exception_type) \
191  do { \
192  static_assert(std::is_base_of_v<std::exception, _exception_type>); \
193  if (!(_condition)) { \
194  cudf::detail::cudf_fail<_exception_type>( \
195  [&]() -> std::string { return _reason; }, __LINE__, __FILE__); \
196  } \
197  } while (0)
198 
199 #define CUDF_EXPECTS_2(_condition, _reason) CUDF_EXPECTS_3(_condition, _reason, cudf::logic_error)
200 
202 
223 #define CUDF_FAIL(...) \
224  GET_CUDF_FAIL_MACRO(__VA_ARGS__, CUDF_FAIL_2, CUDF_FAIL_1) \
225  (__VA_ARGS__)
226 
228 
229 #define GET_CUDF_FAIL_MACRO(_1, _2, NAME, ...) NAME
230 
231 #define CUDF_FAIL_2(_what, _exception_type) \
232  cudf::detail::cudf_fail<_exception_type>( \
233  [&]() -> std::string { return _what; }, __LINE__, __FILE__)
234 
235 #define CUDF_FAIL_1(_what) CUDF_FAIL_2(_what, cudf::logic_error)
236 
238 
239 namespace CUDF_EXPORT cudf {
240 namespace detail {
241 // @cond
242 inline void throw_cuda_error(cudaError_t error, char const* file, unsigned int line)
243 {
244  // Calls cudaGetLastError to clear the error status. It is nearly certain that a fatal error
245  // occurred if it still returns the same error after a cleanup.
246  cudaGetLastError();
247  auto const last = cudaFree(nullptr);
248  auto const msg = std::string{"CUDA error encountered at: " + std::string{file} + ":" +
249  std::to_string(line) + ": " + std::to_string(error) + " " +
250  cudaGetErrorName(error) + " " + cudaGetErrorString(error)};
251  // Call cudaDeviceSynchronize to ensure `last` did not result from an asynchronous error.
252  // between two calls.
253  if (error == last && last == cudaDeviceSynchronize()) {
254  throw fatal_cuda_error{"Fatal " + msg, error};
255  } else {
256  throw cuda_error{msg, error};
257  }
258 }
259 // @endcond
260 
261 // @cond
262 template <typename Exception, typename MsgFunc>
263 [[noreturn]] void cudf_fail(MsgFunc&& msg_func, int line_number, char const* filename)
264 {
265  std::string const msg = std::forward<MsgFunc>(msg_func)();
266  throw Exception{std::string{"CUDF failure at: "} + filename + ":" + std::to_string(line_number) +
267  ": " + (msg.empty() ? "(no message)" : msg)};
268 }
269 // @endcond
270 } // namespace detail
271 } // namespace CUDF_EXPORT cudf
272 
280 #define CUDF_CUDA_TRY(call) \
281  do { \
282  cudaError_t const status = (call); \
283  if (cudaSuccess != status) { cudf::detail::throw_cuda_error(status, __FILE__, __LINE__); } \
284  } while (0);
285 
299 #ifndef NDEBUG
300 #define CUDF_CHECK_CUDA(stream) \
301  do { \
302  CUDF_CUDA_TRY(cudaStreamSynchronize(stream)); \
303  CUDF_CUDA_TRY(cudaPeekAtLastError()); \
304  } while (0);
305 #else
306 #define CUDF_CHECK_CUDA(stream) CUDF_CUDA_TRY(cudaPeekAtLastError());
307 #endif
Error codes for libcudf operations.
constexpr char const * to_string(errc error)
Convert an errc error code to a human-readable string.
Definition: errc.hpp:37
errc
An enumeration of error codes that can occur during operations.
Definition: errc.hpp:26
cuDF interfaces
Definition: host_udf.hpp:26
Exception thrown when a CUDA error is encountered.
Definition: error.hpp:63
cuda_error(std::string const &message, cudaError_t const &error)
Construct a new cuda error object with error message and code.
Definition: error.hpp:70
cudaError_t _cudaError
CUDA error code.
Definition: error.hpp:83
cudaError_t error_code() const
Returns the CUDA error code associated with the exception.
Definition: error.hpp:80
Exception thrown when an operation is attempted on an unsupported dtype.
Definition: error.hpp:97
data_type_error(std::string const &message)
Construct a new data_type_error object with error message.
Definition: error.hpp:110
data_type_error(char const *const message)
Constructs a data_type_error with the error message.
Definition: error.hpp:103
Exception type thrown when evaluating an operator function results in an error (e....
Definition: error.hpp:118
char const * what() const noexcept override
Get the error message.
Definition: error.hpp:131
evaluation_error(errc error, std::string message)
Construct a new evaluation error object.
Definition: error.hpp:125
errc error_code() const
Get the error code that occurred during evaluation.
Definition: error.hpp:137
Exception thrown when logical precondition is violated.
Definition: error.hpp:35
logic_error(char const *const message)
Constructs a logic_error with the error message.
Definition: error.hpp:41
logic_error(std::string const &message)
Construct a new logic error object with error message.
Definition: error.hpp:48