Commit 390c280b by Eric Junyuan Xie Committed by Tianqi Chen

sync logging improvement from dmlc (#86)

* fix glog

* sync logging improvement from dmlc
parent 94fa45f8
......@@ -37,6 +37,14 @@
#define DMLC_LOG_CUSTOMIZE 0
#endif
/*!
* \brief Wheter to print stack trace for fatal error,
* enabled on linux when using gcc.
*/
#if (!defined(DMLC_LOG_STACK_TRACE) && defined(__GNUC__))
#define DMLC_LOG_STACK_TRACE 1
#endif
/*! \brief whether compile with hdfs support */
#ifndef DMLC_USE_HDFS
#define DMLC_USE_HDFS 0
......@@ -201,7 +209,7 @@ inline T *BeginPtr(std::vector<T> &vec) { // NOLINT(*)
}
}
/*!
* \brief get the beginning address of a vector
* \brief get the beginning address of a const vector
* \param vec input vector
* \return beginning address of a vector
*/
......@@ -214,7 +222,7 @@ inline const T *BeginPtr(const std::vector<T> &vec) {
}
}
/*!
* \brief get the beginning address of a vector
* \brief get the beginning address of a string
* \param str input string
* \return beginning address of a string
*/
......@@ -223,7 +231,7 @@ inline char* BeginPtr(std::string &str) { // NOLINT(*)
return &str[0];
}
/*!
* \brief get the beginning address of a vector
* \brief get the beginning address of a const string
* \param str input string
* \return beginning address of a string
*/
......
......@@ -14,6 +14,10 @@
#include <stdexcept>
#include "./base.h"
#if DMLC_LOG_STACK_TRACE
#include <execinfo.h>
#endif
namespace dmlc {
/*!
* \brief exception class that will be thrown by
......@@ -57,17 +61,50 @@ inline void InitLogging(const char* argv0) {
// DO NOTHING
}
class LogCheckError {
public:
LogCheckError() : str(nullptr) {}
explicit LogCheckError(const std::string& str_) : str(new std::string(str_)) {}
~LogCheckError() { if (str != nullptr) delete str; }
operator bool() {return str != nullptr; }
std::string* str;
};
#define DEFINE_CHECK_FUNC(name, op) \
template <typename X, typename Y> \
inline LogCheckError LogCheck##name(const X& x, const Y& y) { \
if (x op y) return LogCheckError(); \
std::ostringstream os; \
os << " (" << x << " vs. " << y << ") "; /* CHECK_XX(x, y) requires x and y can be serialized to string. Use CHECK(x OP y) otherwise. NOLINT(*) */ \
return LogCheckError(os.str()); \
} \
inline LogCheckError LogCheck##name(int x, int y) { \
return LogCheck##name<int, int>(x, y); \
}
#define CHECK_BINARY_OP(name, op, x, y) \
if (dmlc::LogCheckError _check_err = dmlc::LogCheck##name(x, y)) \
dmlc::LogMessageFatal(__FILE__, __LINE__).stream() \
<< "Check failed: " << #x " " #op " " #y << *(_check_err.str)
DEFINE_CHECK_FUNC(_LT, <)
DEFINE_CHECK_FUNC(_GT, >)
DEFINE_CHECK_FUNC(_LE, <=)
DEFINE_CHECK_FUNC(_GE, >=)
DEFINE_CHECK_FUNC(_EQ, ==)
DEFINE_CHECK_FUNC(_NE, !=)
// Always-on checking
#define CHECK(x) \
if (!(x)) \
dmlc::LogMessageFatal(__FILE__, __LINE__).stream() << "Check " \
"failed: " #x << ' '
#define CHECK_LT(x, y) CHECK((x) < (y))
#define CHECK_GT(x, y) CHECK((x) > (y))
#define CHECK_LE(x, y) CHECK((x) <= (y))
#define CHECK_GE(x, y) CHECK((x) >= (y))
#define CHECK_EQ(x, y) CHECK((x) == (y))
#define CHECK_NE(x, y) CHECK((x) != (y))
dmlc::LogMessageFatal(__FILE__, __LINE__).stream() \
<< "Check failed: " #x << ' '
#define CHECK_LT(x, y) CHECK_BINARY_OP(_LT, <, x, y)
#define CHECK_GT(x, y) CHECK_BINARY_OP(_GT, >, x, y)
#define CHECK_LE(x, y) CHECK_BINARY_OP(_LE, <=, x, y)
#define CHECK_GE(x, y) CHECK_BINARY_OP(_GE, >=, x, y)
#define CHECK_EQ(x, y) CHECK_BINARY_OP(_EQ, ==, x, y)
#define CHECK_NE(x, y) CHECK_BINARY_OP(_NE, !=, x, y)
#define CHECK_NOTNULL(x) \
((x) == NULL ? dmlc::LogMessageFatal(__FILE__, __LINE__).stream() << "Check notnull: " #x << ' ', (x) : (x)) // NOLINT(*)
// Debug-only checking.
......@@ -211,6 +248,20 @@ class LogMessageFatal : public LogMessage {
public:
LogMessageFatal(const char* file, int line) : LogMessage(file, line) {}
~LogMessageFatal() {
#if DMLC_LOG_STACK_TRACE
const int MAX_STACK_SIZE = 256;
void *stack[MAX_STACK_SIZE];
int nframes = backtrace(stack, MAX_STACK_SIZE);
log_stream_ << "\n\n" << "Stack trace returned " << nframes << " entries:\n";
char **msgs = backtrace_symbols(stack, nframes);
if (msgs != nullptr) {
for (int i = 0; i < nframes; ++i) {
log_stream_ << "[bt] (" << i << ") " << msgs[i] << "\n";
}
}
#endif
log_stream_ << "\n";
abort();
}
......@@ -228,6 +279,20 @@ class LogMessageFatal {
}
std::ostringstream &stream() { return log_stream_; }
~LogMessageFatal() DMLC_THROW_EXCEPTION {
#if DMLC_LOG_STACK_TRACE
const int MAX_STACK_SIZE = 256;
void *stack[MAX_STACK_SIZE];
int nframes = backtrace(stack, MAX_STACK_SIZE);
log_stream_ << "\n\n" << "Stack trace returned " << nframes << " entries:\n";
char **msgs = backtrace_symbols(stack, nframes);
if (msgs != nullptr) {
for (int i = 0; i < nframes; ++i) {
log_stream_ << "[bt] (" << i << ") " << msgs[i] << "\n";
}
}
#endif
// throwing out of destructor is evil
// hopefully we can do it here
// also log the message before throw
......
......@@ -431,7 +431,7 @@ inline Op& Op::set_attr( // NOLINT(*)
pm.attr_name_ = attr_name;
*pmap = std::move(pm);
}
CHECK_EQ(pmap->type(), typeid(OpMap<ValueType>))
CHECK(pmap->type() == typeid(OpMap<ValueType>))
<< "Attribute " << attr_name
<< " of operator " << this->name
<< " is registered as inconsistent types"
......
......@@ -41,7 +41,7 @@ Graph PlaceDevice(Graph src) {
if (it != inode.source->attrs.dict.end()) {
const std::string& device_group = it->second;
auto dit = device_assign_map.find(device_group);
CHECK_NE(dit, device_assign_map.end())
CHECK(dit != device_assign_map.end())
<< "The device assignment not found for group " << device_group;
device[nid] = dit->second;
} else {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment