1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
#ifndef C10_UTIL_EXCEPTION_H_
#define C10_UTIL_EXCEPTION_H_
#include "c10/macros/Macros.h"
#include "c10/util/StringUtil.h"
#include <cstddef>
#include <exception>
#include <ostream>
#include <sstream>
#include <string>
#include <vector>
#if defined(_MSC_VER) && _MSC_VER <= 1900
#define __func__ __FUNCTION__
#endif
namespace c10 {
/// The primary ATen error class.
/// Provides a complete error message with source location information via
/// `what()`, and a more concise message via `what_without_backtrace()`. Should
/// primarily be used with the `AT_ERROR` macro.
///
/// NB: c10::Error is handled specially by the default torch to suppress the
/// backtrace, see torch/csrc/Exceptions.h
class C10_API Error : public std::exception {
std::vector<std::string> msg_stack_;
std::string backtrace_;
// These two are derived fields from msg_stack_ and backtrace_, but we need
// fields for the strings so that we can return a const char* (as the
// signature of std::exception requires).
std::string msg_;
std::string msg_without_backtrace_;
// This is a little debugging trick: you can stash a relevant pointer
// in caller, and then when you catch the exception, you can compare
// against pointers you have on hand to get more information about
// where the exception came from. In Caffe2, this is used to figure
// out which operator raised an exception.
const void* caller_;
public:
Error(
const std::string& msg,
const std::string& backtrace,
const void* caller = nullptr);
Error(SourceLocation source_location, const std::string& msg);
Error(
const char* file,
const int line,
const char* condition,
const std::string& msg,
const std::string& backtrace,
const void* caller = nullptr);
void AppendMessage(const std::string& msg);
// Compute the full message from msg_ and msg_without_backtrace_
// TODO: Maybe this should be private
std::string msg() const;
std::string msg_without_backtrace() const;
const std::vector<std::string>& msg_stack() const {
return msg_stack_;
}
/// Returns the complete error message, including the source location.
const char* what() const noexcept override {
return msg_.c_str();
}
const void* caller() const noexcept {
return caller_;
}
/// Returns only the error message string, without source location.
const char* what_without_backtrace() const noexcept {
return msg_without_backtrace_.c_str();
}
};
class C10_API Warning {
using handler_t =
void (*)(const SourceLocation& source_location, const char* msg);
public:
/// Issue a warning with a given message. Dispatched to the current
/// warning handler.
static void warn(SourceLocation source_location, std::string msg);
/// Sets the global warning handler. This is not thread-safe, so it should
/// generally be called once during initialization.
static void set_warning_handler(handler_t handler);
/// The default warning handler. Prints the message to stderr.
static void print_warning(
const SourceLocation& source_location,
const char* msg);
private:
static handler_t warning_handler_;
};
// A utility function to return an exception std::string by prepending its
// exception type before its what() content
C10_API std::string GetExceptionString(const std::exception& e);
} // namespace c10
// TODO: variants that print the expression tested and thus don't require
// strings
// TODO: CAFFE_ENFORCE_WITH_CALLER style macro
// TODO: move AT_ERROR to C10_ERROR
// TODO: consolidate the enforce and assert messages. Assert is a bit confusing
// as c++ assert quits, while this throws.
// TODO: merge AT_CHECK with AT_ASSERTM. CHECK in fbcode means strict failure if
// not met.
#define AT_ERROR(...) \
throw ::c10::Error({__func__, __FILE__, __LINE__}, ::c10::str(__VA_ARGS__))
#define AT_WARN(...) \
::c10::Warning::warn({__func__, __FILE__, __LINE__}, ::c10::str(__VA_ARGS__))
#define AT_ASSERT(cond) \
if (!(cond)) { \
AT_ERROR( \
#cond " ASSERT FAILED at ", \
__FILE__, \
":", \
__LINE__, \
", please report a bug to PyTorch."); \
}
#define AT_ASSERTM(cond, ...) \
if (!(cond)) { \
AT_ERROR(::c10::str( \
#cond, \
" ASSERT FAILED at ", \
__FILE__, \
":", \
__LINE__, \
", please report a bug to PyTorch. ", \
__VA_ARGS__)); \
}
#define AT_CHECK(cond, ...) \
if (!(cond)) { \
AT_ERROR(::c10::str(__VA_ARGS__)); \
}
#endif // C10_UTIL_EXCEPTION_H_
|