2012-05-14 20:37:10 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
2014-07-21 09:11:20 +00:00
|
|
|
#include <cxxabi.h>
|
2012-05-14 20:37:10 +00:00
|
|
|
|
2017-02-07 16:36:12 +00:00
|
|
|
#include <Poco/String.h>
|
|
|
|
|
2015-09-29 19:19:54 +00:00
|
|
|
#include <common/logger_useful.h>
|
2013-11-18 19:18:03 +00:00
|
|
|
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <IO/WriteHelpers.h>
|
2017-04-27 15:19:11 +00:00
|
|
|
#include <IO/Operators.h>
|
|
|
|
#include <IO/ReadBufferFromString.h>
|
2012-05-14 20:37:10 +00:00
|
|
|
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <Common/Exception.h>
|
2010-03-01 16:59:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
2011-12-12 06:15:34 +00:00
|
|
|
|
2016-01-11 21:46:36 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
extern const int POCO_EXCEPTION;
|
|
|
|
extern const int STD_EXCEPTION;
|
|
|
|
extern const int UNKNOWN_EXCEPTION;
|
|
|
|
extern const int CANNOT_TRUNCATE_FILE;
|
2016-01-11 21:46:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-15 11:59:39 +00:00
|
|
|
void throwFromErrno(const std::string & s, int code, int e)
|
2012-05-14 20:37:10 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
const size_t buf_size = 128;
|
|
|
|
char buf[buf_size];
|
2016-11-03 19:59:53 +00:00
|
|
|
#ifndef _GNU_SOURCE
|
2017-04-01 07:20:54 +00:00
|
|
|
const char * unknown_message = "Unknown error ";
|
|
|
|
int rc = strerror_r(e, buf, buf_size);
|
2016-11-03 19:59:53 +00:00
|
|
|
#ifdef __APPLE__
|
2017-04-01 07:20:54 +00:00
|
|
|
if (rc != 0 && rc != EINVAL)
|
2016-11-03 19:59:53 +00:00
|
|
|
#else
|
2017-04-01 07:20:54 +00:00
|
|
|
if (rc != 0)
|
2016-11-03 19:59:53 +00:00
|
|
|
#endif
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
std::string tmp = std::to_string(code);
|
|
|
|
const char * code = tmp.c_str();
|
|
|
|
strcpy(buf, unknown_message);
|
|
|
|
strcpy(buf + strlen(unknown_message), code);
|
|
|
|
}
|
|
|
|
throw ErrnoException(s + ", errno: " + toString(e) + ", strerror: " + std::string(buf), code, e);
|
2016-10-26 22:27:38 +00:00
|
|
|
#else
|
2017-04-01 07:20:54 +00:00
|
|
|
throw ErrnoException(s + ", errno: " + toString(e) + ", strerror: " + std::string(strerror_r(e, buf, sizeof(buf))), code, e);
|
2016-10-26 22:27:38 +00:00
|
|
|
#endif
|
2012-05-14 20:37:10 +00:00
|
|
|
}
|
|
|
|
|
2013-11-02 23:42:10 +00:00
|
|
|
|
2015-03-06 16:47:35 +00:00
|
|
|
inline std::string demangle(const char * const mangled, int & status)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
const auto demangled_str = abi::__cxa_demangle(mangled, 0, 0, &status);
|
|
|
|
std::string demangled{demangled_str};
|
|
|
|
free(demangled_str);
|
2015-03-06 16:47:35 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
return demangled;
|
2015-03-06 16:47:35 +00:00
|
|
|
}
|
2013-11-02 23:42:10 +00:00
|
|
|
|
2015-08-12 03:57:32 +00:00
|
|
|
void tryLogCurrentException(const char * log_name, const std::string & start_of_message)
|
2015-03-27 13:10:35 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
tryLogCurrentException(&Logger::get(log_name), start_of_message);
|
2015-03-27 13:10:35 +00:00
|
|
|
}
|
|
|
|
|
2015-08-12 03:57:32 +00:00
|
|
|
void tryLogCurrentException(Poco::Logger * logger, const std::string & start_of_message)
|
2013-11-18 19:18:03 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
LOG_ERROR(logger, start_of_message << (start_of_message.empty() ? "" : ": ") << getCurrentExceptionMessage(true));
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
}
|
2015-06-29 21:35:35 +00:00
|
|
|
}
|
|
|
|
|
2017-02-07 16:36:12 +00:00
|
|
|
std::string getCurrentExceptionMessage(bool with_stacktrace, bool check_embedded_stacktrace)
|
2015-06-29 21:35:35 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
std::stringstream stream;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
catch (const Exception & e)
|
|
|
|
{
|
2017-04-13 16:12:56 +00:00
|
|
|
stream << getExceptionMessage(e, with_stacktrace, check_embedded_stacktrace);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
catch (const Poco::Exception & e)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
stream << "Poco::Exception. Code: " << ErrorCodes::POCO_EXCEPTION << ", e.code() = " << e.code()
|
|
|
|
<< ", e.displayText() = " << e.displayText() << ", e.what() = " << e.what();
|
|
|
|
}
|
|
|
|
catch (...) {}
|
|
|
|
}
|
|
|
|
catch (const std::exception & e)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
int status = 0;
|
|
|
|
auto name = demangle(typeid(e).name(), status);
|
|
|
|
|
|
|
|
if (status)
|
|
|
|
name += " (demangling status: " + toString(status) + ")";
|
|
|
|
|
|
|
|
stream << "std::exception. Code: " << ErrorCodes::STD_EXCEPTION << ", type: " << name << ", e.what() = " << e.what();
|
|
|
|
}
|
|
|
|
catch (...) {}
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
int status = 0;
|
|
|
|
auto name = demangle(abi::__cxa_current_exception_type()->name(), status);
|
|
|
|
|
|
|
|
if (status)
|
|
|
|
name += " (demangling status: " + toString(status) + ")";
|
|
|
|
|
|
|
|
stream << "Unknown exception. Code: " << ErrorCodes::UNKNOWN_EXCEPTION << ", type: " << name;
|
|
|
|
}
|
|
|
|
catch (...) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
return stream.str();
|
2013-11-18 19:18:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-01 20:30:46 +00:00
|
|
|
int getCurrentExceptionCode()
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
catch (const Exception & e)
|
|
|
|
{
|
|
|
|
return e.code();
|
|
|
|
}
|
|
|
|
catch (const Poco::Exception & e)
|
|
|
|
{
|
|
|
|
return ErrorCodes::POCO_EXCEPTION;
|
|
|
|
}
|
|
|
|
catch (const std::exception & e)
|
|
|
|
{
|
|
|
|
return ErrorCodes::STD_EXCEPTION;
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
return ErrorCodes::UNKNOWN_EXCEPTION;
|
|
|
|
}
|
2017-02-01 20:30:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-08 14:39:30 +00:00
|
|
|
void rethrowFirstException(const Exceptions & exceptions)
|
2013-11-02 23:42:10 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
for (size_t i = 0, size = exceptions.size(); i < size; ++i)
|
|
|
|
if (exceptions[i])
|
|
|
|
std::rethrow_exception(exceptions[i]);
|
2015-10-05 05:40:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void tryLogException(std::exception_ptr e, const char * log_name, const std::string & start_of_message)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
std::rethrow_exception(e);
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
tryLogCurrentException(log_name, start_of_message);
|
|
|
|
}
|
2015-10-05 05:40:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void tryLogException(std::exception_ptr e, Poco::Logger * logger, const std::string & start_of_message)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
std::rethrow_exception(e);
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
tryLogCurrentException(logger, start_of_message);
|
|
|
|
}
|
2015-10-05 05:40:27 +00:00
|
|
|
}
|
|
|
|
|
2017-04-13 16:12:56 +00:00
|
|
|
std::string getExceptionMessage(const Exception & e, bool with_stacktrace, bool check_embedded_stacktrace)
|
|
|
|
{
|
|
|
|
std::stringstream stream;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
std::string text = e.displayText();
|
|
|
|
|
|
|
|
bool has_embedded_stack_trace = false;
|
|
|
|
if (check_embedded_stacktrace)
|
|
|
|
{
|
|
|
|
auto embedded_stack_trace_pos = text.find("Stack trace");
|
|
|
|
has_embedded_stack_trace = embedded_stack_trace_pos != std::string::npos;
|
|
|
|
if (!with_stacktrace && has_embedded_stack_trace)
|
|
|
|
{
|
|
|
|
text.resize(embedded_stack_trace_pos);
|
|
|
|
Poco::trimRightInPlace(text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
stream << "Code: " << e.code() << ", e.displayText() = " << text << ", e.what() = " << e.what();
|
|
|
|
|
|
|
|
if (with_stacktrace && !has_embedded_stack_trace)
|
|
|
|
stream << ", Stack trace:\n\n" << e.getStackTrace().toString();
|
|
|
|
}
|
|
|
|
catch (...) {}
|
|
|
|
|
|
|
|
return stream.str();
|
|
|
|
}
|
|
|
|
|
2015-10-05 05:40:27 +00:00
|
|
|
std::string getExceptionMessage(std::exception_ptr e, bool with_stacktrace)
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
std::rethrow_exception(e);
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
return getCurrentExceptionMessage(with_stacktrace);
|
|
|
|
}
|
2013-11-02 23:42:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-04-27 15:19:11 +00:00
|
|
|
std::string ExecutionStatus::serializeText() const
|
|
|
|
{
|
2017-07-31 21:39:24 +00:00
|
|
|
WriteBufferFromOwnString wb;
|
|
|
|
wb << code << "\n" << escape << message;
|
|
|
|
return wb.str();
|
2017-04-27 15:19:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ExecutionStatus::deserializeText(const std::string & data)
|
|
|
|
{
|
|
|
|
ReadBufferFromString rb(data);
|
2017-05-31 14:01:08 +00:00
|
|
|
rb >> code >> "\n" >> escape >> message;
|
2017-04-27 15:19:11 +00:00
|
|
|
}
|
|
|
|
|
2017-07-27 13:11:16 +00:00
|
|
|
bool ExecutionStatus::tryDeserializeText(const std::string & data)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
deserializeText(data);
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-04-27 15:19:11 +00:00
|
|
|
ExecutionStatus ExecutionStatus::fromCurrentException(const std::string & start_of_message)
|
|
|
|
{
|
|
|
|
return ExecutionStatus(getCurrentExceptionCode(), start_of_message + ": " + getCurrentExceptionMessage(false, true));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-01 16:59:51 +00:00
|
|
|
}
|