2021-05-05 22:44:53 +00:00
|
|
|
#include <c10/util/Exception.h>
|
2020-04-10 19:03:54 +00:00
|
|
|
#include <c10/util/Logging.h>
|
2021-05-05 22:44:53 +00:00
|
|
|
#include <c10/util/Type.h>
|
Make AT_ASSERT/AT_ERROR non-printf based, other tweaks (#7104)
* Make AT_ASSERT/AT_ERROR non-printf based, other tweaks
- AT_ASSERT/AT_ERROR don't take printf strings anymore; instead,
they take a comma-separated list of things you wanted to print
(bringing it inline with Caffe2's conventions).
Instead of AT_ASSERT(x == 0, "%d is not zero", x)
you write AT_ASSERT(x == 0, x, " is not zero")
This is done by way of a new variadic template at::str(), which
takes a list of arguments and cats their string reps (as per
operator<<) together.
- A bunch of the demangling logic that was in Error.h is now
moved to Error.cpp (better header hygiene.) Also, demangle
has been moved out to its own helper function, and also
a new helper demangle_type (from Caffe2) added.
- A bunch of AT_ASSERT converted into AT_CHECK, to more properly
convey which checks can be caused by user error, and which are
due to logic error in ATen.
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* CR
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* Fix test failure.
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* buildfix
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* More fixes.
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* One more fix
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* Try harder
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
2018-05-01 14:28:31 +00:00
|
|
|
|
2021-05-05 22:44:53 +00:00
|
|
|
#include <sstream>
|
2018-06-04 04:11:29 +00:00
|
|
|
#include <string>
|
2022-12-27 07:34:12 +00:00
|
|
|
#include <utility>
|
Make AT_ASSERT/AT_ERROR non-printf based, other tweaks (#7104)
* Make AT_ASSERT/AT_ERROR non-printf based, other tweaks
- AT_ASSERT/AT_ERROR don't take printf strings anymore; instead,
they take a comma-separated list of things you wanted to print
(bringing it inline with Caffe2's conventions).
Instead of AT_ASSERT(x == 0, "%d is not zero", x)
you write AT_ASSERT(x == 0, x, " is not zero")
This is done by way of a new variadic template at::str(), which
takes a list of arguments and cats their string reps (as per
operator<<) together.
- A bunch of the demangling logic that was in Error.h is now
moved to Error.cpp (better header hygiene.) Also, demangle
has been moved out to its own helper function, and also
a new helper demangle_type (from Caffe2) added.
- A bunch of AT_ASSERT converted into AT_CHECK, to more properly
convey which checks can be caused by user error, and which are
due to logic error in ATen.
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* CR
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* Fix test failure.
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* buildfix
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* More fixes.
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* One more fix
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* Try harder
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
2018-05-01 14:28:31 +00:00
|
|
|
|
2018-10-15 20:28:08 +00:00
|
|
|
namespace c10 {
|
Make AT_ASSERT/AT_ERROR non-printf based, other tweaks (#7104)
* Make AT_ASSERT/AT_ERROR non-printf based, other tweaks
- AT_ASSERT/AT_ERROR don't take printf strings anymore; instead,
they take a comma-separated list of things you wanted to print
(bringing it inline with Caffe2's conventions).
Instead of AT_ASSERT(x == 0, "%d is not zero", x)
you write AT_ASSERT(x == 0, x, " is not zero")
This is done by way of a new variadic template at::str(), which
takes a list of arguments and cats their string reps (as per
operator<<) together.
- A bunch of the demangling logic that was in Error.h is now
moved to Error.cpp (better header hygiene.) Also, demangle
has been moved out to its own helper function, and also
a new helper demangle_type (from Caffe2) added.
- A bunch of AT_ASSERT converted into AT_CHECK, to more properly
convey which checks can be caused by user error, and which are
due to logic error in ATen.
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* CR
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* Fix test failure.
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* buildfix
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* More fixes.
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* One more fix
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* Try harder
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
2018-05-01 14:28:31 +00:00
|
|
|
|
2024-05-09 01:46:57 +00:00
|
|
|
Error::Error(std::string msg, Backtrace backtrace, const void* caller)
|
2020-05-04 18:51:15 +00:00
|
|
|
: msg_(std::move(msg)), backtrace_(std::move(backtrace)), caller_(caller) {
|
|
|
|
|
refresh_what();
|
2018-08-04 02:09:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// PyTorch-style error message
|
2018-10-24 23:16:26 +00:00
|
|
|
// Error::Error(SourceLocation source_location, const std::string& msg)
|
|
|
|
|
// NB: This is defined in Logging.cpp for access to GetFetchStackTrace
|
Make AT_ASSERT/AT_ERROR non-printf based, other tweaks (#7104)
* Make AT_ASSERT/AT_ERROR non-printf based, other tweaks
- AT_ASSERT/AT_ERROR don't take printf strings anymore; instead,
they take a comma-separated list of things you wanted to print
(bringing it inline with Caffe2's conventions).
Instead of AT_ASSERT(x == 0, "%d is not zero", x)
you write AT_ASSERT(x == 0, x, " is not zero")
This is done by way of a new variadic template at::str(), which
takes a list of arguments and cats their string reps (as per
operator<<) together.
- A bunch of the demangling logic that was in Error.h is now
moved to Error.cpp (better header hygiene.) Also, demangle
has been moved out to its own helper function, and also
a new helper demangle_type (from Caffe2) added.
- A bunch of AT_ASSERT converted into AT_CHECK, to more properly
convey which checks can be caused by user error, and which are
due to logic error in ATen.
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* CR
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* Fix test failure.
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* buildfix
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* More fixes.
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* One more fix
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
* Try harder
Signed-off-by: Edward Z. Yang <ezyang@fb.com>
2018-05-01 14:28:31 +00:00
|
|
|
|
2018-08-04 02:09:51 +00:00
|
|
|
// Caffe2-style error message
|
|
|
|
|
Error::Error(
|
|
|
|
|
const char* file,
|
2018-12-26 08:46:13 +00:00
|
|
|
const uint32_t line,
|
2018-08-04 02:09:51 +00:00
|
|
|
const char* condition,
|
|
|
|
|
const std::string& msg,
|
2024-05-09 01:46:57 +00:00
|
|
|
Backtrace backtrace,
|
2018-08-04 02:09:51 +00:00
|
|
|
const void* caller)
|
|
|
|
|
: Error(
|
|
|
|
|
str("[enforce fail at ",
|
|
|
|
|
detail::StripBasename(file),
|
|
|
|
|
":",
|
|
|
|
|
line,
|
|
|
|
|
"] ",
|
|
|
|
|
condition,
|
|
|
|
|
". ",
|
2020-05-04 18:51:15 +00:00
|
|
|
msg),
|
2024-05-09 01:46:57 +00:00
|
|
|
std::move(backtrace),
|
2018-08-04 02:09:51 +00:00
|
|
|
caller) {}
|
|
|
|
|
|
2020-05-04 18:51:15 +00:00
|
|
|
std::string Error::compute_what(bool include_backtrace) const {
|
|
|
|
|
std::ostringstream oss;
|
|
|
|
|
|
|
|
|
|
oss << msg_;
|
|
|
|
|
|
|
|
|
|
if (context_.size() == 1) {
|
|
|
|
|
// Fold error and context in one line
|
|
|
|
|
oss << " (" << context_[0] << ")";
|
|
|
|
|
} else {
|
|
|
|
|
for (const auto& c : context_) {
|
|
|
|
|
oss << "\n " << c;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-09 01:46:57 +00:00
|
|
|
if (include_backtrace && backtrace_) {
|
|
|
|
|
oss << "\n" << backtrace_->get();
|
2020-05-04 18:51:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return oss.str();
|
2018-08-04 02:09:51 +00:00
|
|
|
}
|
|
|
|
|
|
2024-05-13 20:17:41 +00:00
|
|
|
const Backtrace& Error::backtrace() const {
|
2024-05-09 01:46:57 +00:00
|
|
|
return backtrace_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char* Error::what() const noexcept {
|
|
|
|
|
return what_
|
|
|
|
|
.ensure([this] {
|
|
|
|
|
try {
|
|
|
|
|
return compute_what(/*include_backtrace*/ true);
|
|
|
|
|
} catch (...) {
|
|
|
|
|
// what() is noexcept, we need to return something here.
|
|
|
|
|
return std::string{"<Error computing Error::what()>"};
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.c_str();
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-04 18:51:15 +00:00
|
|
|
void Error::refresh_what() {
|
2024-05-09 01:46:57 +00:00
|
|
|
// Do not compute what_ eagerly, as it would trigger the computation of the
|
|
|
|
|
// backtrace. Instead, invalidate it, it will be computed on first access.
|
|
|
|
|
// refresh_what() is only called by non-const public methods which are not
|
|
|
|
|
// supposed to be called concurrently with any other method, so it is safe to
|
|
|
|
|
// invalidate here.
|
|
|
|
|
what_.reset();
|
2020-05-04 18:51:15 +00:00
|
|
|
what_without_backtrace_ = compute_what(/*include_backtrace*/ false);
|
2018-08-04 02:09:51 +00:00
|
|
|
}
|
|
|
|
|
|
2020-05-04 18:51:15 +00:00
|
|
|
void Error::add_context(std::string new_msg) {
|
|
|
|
|
context_.push_back(std::move(new_msg));
|
|
|
|
|
// TODO: Calling add_context O(n) times has O(n^2) cost. We can fix
|
2018-08-04 02:09:51 +00:00
|
|
|
// this perf problem by populating the fields lazily... if this ever
|
|
|
|
|
// actually is a problem.
|
2020-05-04 18:51:15 +00:00
|
|
|
// NB: If you do fix this, make sure you do it in a thread safe way!
|
|
|
|
|
// what() is almost certainly expected to be thread safe even when
|
|
|
|
|
// accessed across multiple threads
|
|
|
|
|
refresh_what();
|
2018-08-04 02:09:51 +00:00
|
|
|
}
|
|
|
|
|
|
2020-12-14 16:07:45 +00:00
|
|
|
namespace detail {
|
|
|
|
|
|
2021-05-05 22:44:53 +00:00
|
|
|
void torchCheckFail(
|
|
|
|
|
const char* func,
|
|
|
|
|
const char* file,
|
|
|
|
|
uint32_t line,
|
|
|
|
|
const std::string& msg) {
|
2020-12-14 16:07:45 +00:00
|
|
|
throw ::c10::Error({func, file, line}, msg);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-05 22:44:53 +00:00
|
|
|
void torchCheckFail(
|
|
|
|
|
const char* func,
|
|
|
|
|
const char* file,
|
|
|
|
|
uint32_t line,
|
|
|
|
|
const char* msg) {
|
2021-02-02 00:39:12 +00:00
|
|
|
throw ::c10::Error({func, file, line}, msg);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-05 22:44:53 +00:00
|
|
|
void torchInternalAssertFail(
|
|
|
|
|
const char* func,
|
|
|
|
|
const char* file,
|
|
|
|
|
uint32_t line,
|
|
|
|
|
const char* condMsg,
|
|
|
|
|
const char* userMsg) {
|
2021-02-19 20:38:47 +00:00
|
|
|
torchCheckFail(func, file, line, c10::str(condMsg, userMsg));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This should never be called. It is provided in case of compilers
|
|
|
|
|
// that don't do any dead code stripping in debug builds.
|
2021-05-05 22:44:53 +00:00
|
|
|
void torchInternalAssertFail(
|
|
|
|
|
const char* func,
|
|
|
|
|
const char* file,
|
|
|
|
|
uint32_t line,
|
|
|
|
|
const char* condMsg,
|
|
|
|
|
const std::string& userMsg) {
|
2021-02-19 20:38:47 +00:00
|
|
|
torchCheckFail(func, file, line, c10::str(condMsg, userMsg));
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-14 16:07:45 +00:00
|
|
|
} // namespace detail
|
|
|
|
|
|
2022-10-18 20:02:42 +00:00
|
|
|
namespace WarningUtils {
|
2019-11-07 16:32:51 +00:00
|
|
|
|
|
|
|
|
namespace {
|
2021-05-05 22:44:53 +00:00
|
|
|
WarningHandler* getBaseHandler() {
|
|
|
|
|
static WarningHandler base_warning_handler_ = WarningHandler();
|
|
|
|
|
return &base_warning_handler_;
|
2024-05-14 19:35:27 +00:00
|
|
|
}
|
2021-05-05 22:44:53 +00:00
|
|
|
|
|
|
|
|
class ThreadWarningHandler {
|
|
|
|
|
public:
|
|
|
|
|
ThreadWarningHandler() = delete;
|
|
|
|
|
|
|
|
|
|
static WarningHandler* get_handler() {
|
|
|
|
|
if (!warning_handler_) {
|
|
|
|
|
warning_handler_ = getBaseHandler();
|
|
|
|
|
}
|
|
|
|
|
return warning_handler_;
|
|
|
|
|
}
|
2020-03-25 06:49:17 +00:00
|
|
|
|
2021-05-05 22:44:53 +00:00
|
|
|
static void set_handler(WarningHandler* handler) {
|
|
|
|
|
warning_handler_ = handler;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
static thread_local WarningHandler* warning_handler_;
|
|
|
|
|
};
|
2019-12-05 19:20:17 +00:00
|
|
|
|
2021-05-05 22:44:53 +00:00
|
|
|
thread_local WarningHandler* ThreadWarningHandler::warning_handler_ = nullptr;
|
|
|
|
|
|
|
|
|
|
} // namespace
|
2019-11-07 16:32:51 +00:00
|
|
|
|
|
|
|
|
void set_warning_handler(WarningHandler* handler) noexcept(true) {
|
2020-03-25 06:49:17 +00:00
|
|
|
ThreadWarningHandler::set_handler(handler);
|
2018-06-28 04:12:13 +00:00
|
|
|
}
|
|
|
|
|
|
2019-11-07 16:32:51 +00:00
|
|
|
WarningHandler* get_warning_handler() noexcept(true) {
|
2020-03-25 06:49:17 +00:00
|
|
|
return ThreadWarningHandler::get_handler();
|
2019-11-07 16:32:51 +00:00
|
|
|
}
|
|
|
|
|
|
2024-10-29 17:01:53 +00:00
|
|
|
static bool warn_always = false;
|
2021-02-08 16:18:50 +00:00
|
|
|
|
|
|
|
|
void set_warnAlways(bool setting) noexcept(true) {
|
2021-05-05 22:44:53 +00:00
|
|
|
warn_always = setting;
|
2021-02-08 16:18:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool get_warnAlways() noexcept(true) {
|
2021-05-05 22:44:53 +00:00
|
|
|
return warn_always;
|
2021-02-08 16:18:50 +00:00
|
|
|
}
|
|
|
|
|
|
2021-06-09 00:18:01 +00:00
|
|
|
WarnAlways::WarnAlways(bool setting /*=true*/)
|
|
|
|
|
: prev_setting(get_warnAlways()) {
|
|
|
|
|
set_warnAlways(setting);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WarnAlways::~WarnAlways() {
|
|
|
|
|
set_warnAlways(prev_setting);
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-18 20:02:42 +00:00
|
|
|
} // namespace WarningUtils
|
|
|
|
|
|
|
|
|
|
void warn(const Warning& warning) {
|
|
|
|
|
WarningUtils::ThreadWarningHandler::get_handler()->process(warning);
|
|
|
|
|
}
|
2019-11-07 16:32:51 +00:00
|
|
|
|
2022-10-18 20:02:42 +00:00
|
|
|
Warning::Warning(
|
|
|
|
|
warning_variant_t type,
|
2018-08-01 20:23:08 +00:00
|
|
|
const SourceLocation& source_location,
|
2022-12-27 07:34:12 +00:00
|
|
|
std::string msg,
|
2022-10-18 20:02:42 +00:00
|
|
|
const bool verbatim)
|
|
|
|
|
: type_(type),
|
|
|
|
|
source_location_(source_location),
|
2022-12-27 07:34:12 +00:00
|
|
|
msg_(std::move(msg)),
|
2022-10-18 20:02:42 +00:00
|
|
|
verbatim_(verbatim) {}
|
|
|
|
|
|
|
|
|
|
Warning::Warning(
|
|
|
|
|
warning_variant_t type,
|
|
|
|
|
SourceLocation source_location,
|
|
|
|
|
detail::CompileTimeEmptyString msg,
|
|
|
|
|
const bool verbatim)
|
2022-12-27 07:34:12 +00:00
|
|
|
: Warning(type, source_location, "", verbatim) {}
|
2022-10-18 20:02:42 +00:00
|
|
|
|
|
|
|
|
Warning::Warning(
|
|
|
|
|
warning_variant_t type,
|
|
|
|
|
SourceLocation source_location,
|
|
|
|
|
const char* msg,
|
|
|
|
|
const bool verbatim)
|
|
|
|
|
: type_(type),
|
2022-12-27 07:34:12 +00:00
|
|
|
source_location_(source_location),
|
2022-10-18 20:02:42 +00:00
|
|
|
msg_(std::string(msg)),
|
|
|
|
|
verbatim_(verbatim) {}
|
|
|
|
|
|
|
|
|
|
Warning::warning_variant_t Warning::type() const {
|
|
|
|
|
return type_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const SourceLocation& Warning::source_location() const {
|
|
|
|
|
return source_location_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::string& Warning::msg() const {
|
|
|
|
|
return msg_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Warning::verbatim() const {
|
|
|
|
|
return verbatim_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void WarningHandler::process(const Warning& warning) {
|
|
|
|
|
LOG_AT_FILE_LINE(
|
|
|
|
|
WARNING, warning.source_location().file, warning.source_location().line)
|
|
|
|
|
<< "Warning: " << warning.msg() << " (function "
|
|
|
|
|
<< warning.source_location().function << ")";
|
2018-06-28 04:12:13 +00:00
|
|
|
}
|
|
|
|
|
|
2018-09-22 04:51:21 +00:00
|
|
|
std::string GetExceptionString(const std::exception& e) {
|
|
|
|
|
#ifdef __GXX_RTTI
|
2018-10-15 20:28:08 +00:00
|
|
|
return demangle(typeid(e).name()) + ": " + e.what();
|
2018-09-22 04:51:21 +00:00
|
|
|
#else
|
|
|
|
|
return std::string("Exception (no RTTI available): ") + e.what();
|
|
|
|
|
#endif // __GXX_RTTI
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-15 20:28:08 +00:00
|
|
|
} // namespace c10
|