2019-03-27 15:42:24 +00:00
|
|
|
#include "Exception.h"
|
|
|
|
|
2012-05-14 20:37:10 +00:00
|
|
|
#include <string.h>
|
2014-07-21 09:11:20 +00:00
|
|
|
#include <cxxabi.h>
|
2020-10-15 18:14:04 +00:00
|
|
|
#include <cstdlib>
|
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>
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <IO/WriteHelpers.h>
|
2020-05-30 19:38:25 +00:00
|
|
|
#include <IO/ReadHelpers.h>
|
2017-04-27 15:19:11 +00:00
|
|
|
#include <IO/Operators.h>
|
|
|
|
#include <IO/ReadBufferFromString.h>
|
2020-05-30 19:38:25 +00:00
|
|
|
#include <IO/ReadBufferFromFile.h>
|
2018-04-09 13:52:39 +00:00
|
|
|
#include <common/demangle.h>
|
2020-06-07 17:29:34 +00:00
|
|
|
#include <common/errnoToString.h>
|
2019-08-05 19:41:20 +00:00
|
|
|
#include <Common/formatReadable.h>
|
2019-11-27 09:39:44 +00:00
|
|
|
#include <Common/filesystemHelpers.h>
|
2020-10-29 07:07:42 +00:00
|
|
|
#include <Common/ErrorCodes.h>
|
2019-08-05 19:41:20 +00:00
|
|
|
#include <filesystem>
|
2010-03-01 16:59:51 +00:00
|
|
|
|
2020-04-16 12:31:57 +00:00
|
|
|
#if !defined(ARCADIA_BUILD)
|
|
|
|
# include <Common/config_version.h>
|
|
|
|
#endif
|
|
|
|
|
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;
|
2019-12-30 14:46:02 +00:00
|
|
|
extern const int LOGICAL_ERROR;
|
2020-05-30 19:38:25 +00:00
|
|
|
extern const int CANNOT_ALLOCATE_MEMORY;
|
|
|
|
extern const int CANNOT_MREMAP;
|
2016-01-11 21:46:36 +00:00
|
|
|
}
|
|
|
|
|
2021-03-08 19:05:51 +00:00
|
|
|
/// - Aborts the process if error code is LOGICAL_ERROR.
|
|
|
|
/// - Increments error codes statistics.
|
2021-03-23 20:03:08 +00:00
|
|
|
void handle_error_code([[maybe_unused]] const std::string & msg, int code, bool remote, const Exception::FramePointers & trace)
|
2020-01-02 06:56:53 +00:00
|
|
|
{
|
2020-10-15 18:14:04 +00:00
|
|
|
// In debug builds and builds with sanitizers, treat LOGICAL_ERROR as an assertion failure.
|
2020-02-20 12:29:53 +00:00
|
|
|
// Log the message before we fail.
|
2020-10-16 11:58:47 +00:00
|
|
|
#ifdef ABORT_ON_LOGICAL_ERROR
|
2020-02-20 12:29:53 +00:00
|
|
|
if (code == ErrorCodes::LOGICAL_ERROR)
|
|
|
|
{
|
2020-10-15 18:14:04 +00:00
|
|
|
LOG_FATAL(&Poco::Logger::root(), "Logical error: '{}'.", msg);
|
|
|
|
abort();
|
2020-02-20 12:29:53 +00:00
|
|
|
}
|
|
|
|
#endif
|
2021-03-23 20:03:08 +00:00
|
|
|
|
|
|
|
ErrorCodes::increment(code, remote, msg, trace);
|
2020-01-02 06:56:53 +00:00
|
|
|
}
|
|
|
|
|
2021-01-19 21:42:31 +00:00
|
|
|
Exception::Exception(const std::string & msg, int code, bool remote_)
|
2020-12-12 14:11:47 +00:00
|
|
|
: Poco::Exception(msg, code)
|
2021-01-19 21:42:31 +00:00
|
|
|
, remote(remote_)
|
2020-12-12 14:11:47 +00:00
|
|
|
{
|
2021-03-23 20:03:08 +00:00
|
|
|
handle_error_code(msg, code, remote, getStackFramePointers());
|
2020-12-12 14:11:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Exception::Exception(const std::string & msg, const Exception & nested, int code)
|
|
|
|
: Poco::Exception(msg, nested, code)
|
|
|
|
{
|
2021-03-23 20:03:08 +00:00
|
|
|
handle_error_code(msg, code, remote, getStackFramePointers());
|
2020-12-12 14:11:47 +00:00
|
|
|
}
|
|
|
|
|
2020-01-02 06:56:53 +00:00
|
|
|
Exception::Exception(CreateFromPocoTag, const Poco::Exception & exc)
|
|
|
|
: Poco::Exception(exc.displayText(), ErrorCodes::POCO_EXCEPTION)
|
|
|
|
{
|
2020-01-02 10:29:59 +00:00
|
|
|
#ifdef STD_EXCEPTION_HAS_STACK_TRACE
|
2020-01-02 06:56:53 +00:00
|
|
|
set_stack_trace(exc.get_stack_trace_frames(), exc.get_stack_trace_size());
|
2020-01-02 10:29:59 +00:00
|
|
|
#endif
|
2020-01-02 06:56:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Exception::Exception(CreateFromSTDTag, const std::exception & exc)
|
2020-08-07 14:52:32 +00:00
|
|
|
: Poco::Exception(demangle(typeid(exc).name()) + ": " + String(exc.what()), ErrorCodes::STD_EXCEPTION)
|
2020-01-02 06:56:53 +00:00
|
|
|
{
|
2020-01-02 10:29:59 +00:00
|
|
|
#ifdef STD_EXCEPTION_HAS_STACK_TRACE
|
2020-01-02 06:56:53 +00:00
|
|
|
set_stack_trace(exc.get_stack_trace_frames(), exc.get_stack_trace_size());
|
2020-01-02 10:29:59 +00:00
|
|
|
#endif
|
2020-01-02 06:56:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string getExceptionStackTraceString(const std::exception & e)
|
|
|
|
{
|
|
|
|
#ifdef STD_EXCEPTION_HAS_STACK_TRACE
|
|
|
|
return StackTrace::toString(e.get_stack_trace_frames(), 0, e.get_stack_trace_size());
|
|
|
|
#else
|
2020-01-02 18:55:45 +00:00
|
|
|
if (const auto * db_exception = dynamic_cast<const Exception *>(&e))
|
2020-01-02 16:32:17 +00:00
|
|
|
return db_exception->getStackTraceString();
|
2020-01-02 06:56:53 +00:00
|
|
|
return {};
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string Exception::getStackTraceString() const
|
|
|
|
{
|
|
|
|
#ifdef STD_EXCEPTION_HAS_STACK_TRACE
|
|
|
|
return StackTrace::toString(get_stack_trace_frames(), 0, get_stack_trace_size());
|
|
|
|
#else
|
|
|
|
return trace.toString();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-03-23 20:03:08 +00:00
|
|
|
Exception::FramePointers Exception::getStackFramePointers() const
|
|
|
|
{
|
2021-03-24 06:41:57 +00:00
|
|
|
FramePointers frame_pointers;
|
2021-03-23 20:03:08 +00:00
|
|
|
#ifdef STD_EXCEPTION_HAS_STACK_TRACE
|
|
|
|
{
|
2021-03-24 06:41:57 +00:00
|
|
|
frame_pointers.resize(get_stack_trace_size());
|
|
|
|
for (size_t i = 0; i < frame_pointers.size(); ++i)
|
2021-03-23 20:03:08 +00:00
|
|
|
{
|
2021-03-24 06:41:57 +00:00
|
|
|
frame_pointers[i] = get_stack_trace_frames()[i];
|
2021-03-23 20:03:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
{
|
|
|
|
size_t stack_trace_size = trace.getSize();
|
|
|
|
size_t stack_trace_offset = trace.getOffset();
|
2021-03-24 06:41:57 +00:00
|
|
|
frame_pointers.reserve(stack_trace_size - stack_trace_offset);
|
2021-03-23 20:03:08 +00:00
|
|
|
for (size_t i = stack_trace_offset; i < stack_trace_size; ++i)
|
|
|
|
{
|
2021-03-24 06:41:57 +00:00
|
|
|
frame_pointers.push_back(trace.getFramePointers()[i]);
|
2021-03-23 20:03:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2021-03-24 06:41:57 +00:00
|
|
|
return frame_pointers;
|
2021-03-23 20:03:08 +00:00
|
|
|
}
|
|
|
|
|
2020-01-02 06:56:53 +00:00
|
|
|
|
2020-03-08 21:04:10 +00:00
|
|
|
void throwFromErrno(const std::string & s, int code, int the_errno)
|
2018-11-14 01:11:13 +00:00
|
|
|
{
|
2020-03-08 21:04:10 +00:00
|
|
|
throw ErrnoException(s + ", " + errnoToString(code, the_errno), code, the_errno);
|
2018-11-14 01:11:13 +00:00
|
|
|
}
|
2013-11-02 23:42:10 +00:00
|
|
|
|
2019-08-07 12:52:47 +00:00
|
|
|
void throwFromErrnoWithPath(const std::string & s, const std::string & path, int code, int the_errno)
|
2019-08-06 18:54:06 +00:00
|
|
|
{
|
|
|
|
throw ErrnoException(s + ", " + errnoToString(code, the_errno), code, the_errno, path);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2020-05-30 21:57:37 +00:00
|
|
|
tryLogCurrentException(&Poco::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
|
|
|
{
|
2021-01-29 18:37:57 +00:00
|
|
|
/// Under high memory pressure, any new allocation will definitelly lead
|
|
|
|
/// to MEMORY_LIMIT_EXCEEDED exception.
|
|
|
|
///
|
|
|
|
/// And in this case the exception will not be logged, so let's block the
|
|
|
|
/// MemoryTracker until the exception will be logged.
|
2021-04-14 20:33:36 +00:00
|
|
|
MemoryTracker::LockExceptionInThread lock_memory_tracker(VariableContext::Global);
|
2021-01-29 18:37:57 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
try
|
|
|
|
{
|
2020-05-23 20:13:34 +00:00
|
|
|
if (start_of_message.empty())
|
2020-05-23 22:24:01 +00:00
|
|
|
LOG_ERROR(logger, "{}", getCurrentExceptionMessage(true));
|
2020-05-23 20:13:34 +00:00
|
|
|
else
|
2020-05-23 22:24:01 +00:00
|
|
|
LOG_ERROR(logger, "{}: {}", start_of_message, getCurrentExceptionMessage(true));
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
}
|
2015-06-29 21:35:35 +00:00
|
|
|
}
|
|
|
|
|
2019-12-15 06:34:43 +00:00
|
|
|
static void getNoSpaceLeftInfoMessage(std::filesystem::path path, std::string & msg)
|
2019-08-05 19:41:20 +00:00
|
|
|
{
|
2019-08-06 18:54:06 +00:00
|
|
|
path = std::filesystem::absolute(path);
|
2019-08-05 19:41:20 +00:00
|
|
|
/// It's possible to get ENOSPC for non existent file (e.g. if there are no free inodes and creat() fails)
|
|
|
|
/// So try to get info for existent parent directory.
|
|
|
|
while (!std::filesystem::exists(path) && path.has_relative_path())
|
|
|
|
path = path.parent_path();
|
|
|
|
|
2019-11-27 09:39:44 +00:00
|
|
|
auto fs = getStatVFS(path);
|
|
|
|
auto mount_point = getMountPoint(path).string();
|
2020-05-30 21:35:52 +00:00
|
|
|
|
|
|
|
fmt::format_to(std::back_inserter(msg),
|
|
|
|
"\nTotal space: {}\nAvailable space: {}\nTotal inodes: {}\nAvailable inodes: {}\nMount point: {}",
|
|
|
|
ReadableSize(fs.f_blocks * fs.f_bsize),
|
|
|
|
ReadableSize(fs.f_bavail * fs.f_bsize),
|
|
|
|
formatReadableQuantity(fs.f_files),
|
|
|
|
formatReadableQuantity(fs.f_favail),
|
|
|
|
mount_point);
|
|
|
|
|
2019-08-07 12:52:47 +00:00
|
|
|
#if defined(__linux__)
|
2019-11-27 09:39:44 +00:00
|
|
|
msg += "\nFilesystem: " + getFilesystemName(mount_point);
|
2019-08-07 12:52:47 +00:00
|
|
|
#endif
|
2019-08-05 19:41:20 +00:00
|
|
|
}
|
|
|
|
|
2020-05-30 19:38:25 +00:00
|
|
|
|
|
|
|
/** It is possible that the system has enough memory,
|
|
|
|
* but we have shortage of the number of available memory mappings.
|
|
|
|
* Provide good diagnostic to user in that case.
|
|
|
|
*/
|
|
|
|
static void getNotEnoughMemoryMessage(std::string & msg)
|
|
|
|
{
|
|
|
|
#if defined(__linux__)
|
|
|
|
try
|
|
|
|
{
|
2020-06-08 17:35:45 +00:00
|
|
|
static constexpr size_t buf_size = 1024;
|
2020-05-30 20:02:44 +00:00
|
|
|
char buf[buf_size];
|
|
|
|
|
2020-05-30 19:38:25 +00:00
|
|
|
UInt64 max_map_count = 0;
|
|
|
|
{
|
2020-05-30 20:02:44 +00:00
|
|
|
ReadBufferFromFile file("/proc/sys/vm/max_map_count", buf_size, -1, buf);
|
2020-05-30 19:38:25 +00:00
|
|
|
readText(max_map_count, file);
|
|
|
|
}
|
|
|
|
|
|
|
|
UInt64 num_maps = 0;
|
|
|
|
{
|
2020-05-30 20:02:44 +00:00
|
|
|
ReadBufferFromFile file("/proc/self/maps", buf_size, -1, buf);
|
2020-05-30 19:38:25 +00:00
|
|
|
while (!file.eof())
|
|
|
|
{
|
|
|
|
char * next_pos = find_first_symbols<'\n'>(file.position(), file.buffer().end());
|
|
|
|
file.position() = next_pos;
|
|
|
|
|
|
|
|
if (!file.hasPendingData())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (*file.position() == '\n')
|
|
|
|
{
|
|
|
|
++num_maps;
|
|
|
|
++file.position();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (num_maps > max_map_count * 0.99)
|
|
|
|
{
|
|
|
|
msg += fmt::format(
|
|
|
|
"\nIt looks like that the process is near the limit on number of virtual memory mappings."
|
|
|
|
"\nCurrent number of mappings (/proc/self/maps): {}."
|
|
|
|
"\nLimit on number of mappings (/proc/sys/vm/max_map_count): {}."
|
2020-05-30 20:02:44 +00:00
|
|
|
"\nYou should increase the limit for vm.max_map_count in /etc/sysctl.conf"
|
|
|
|
"\n",
|
2020-05-30 19:38:25 +00:00
|
|
|
num_maps, max_map_count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
msg += "\nCannot obtain additional info about memory usage.";
|
|
|
|
}
|
2020-05-30 19:40:23 +00:00
|
|
|
#else
|
|
|
|
(void)msg;
|
2020-05-30 19:38:25 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-12-15 06:34:43 +00:00
|
|
|
static std::string getExtraExceptionInfo(const std::exception & e)
|
2019-08-05 19:41:20 +00:00
|
|
|
{
|
|
|
|
String msg;
|
|
|
|
try
|
|
|
|
{
|
2021-05-07 21:53:44 +00:00
|
|
|
/// TODO: this has to be adjusted for std::filesystem
|
2020-04-22 05:39:31 +00:00
|
|
|
if (const auto * file_exception = dynamic_cast<const Poco::FileException *>(&e))
|
2019-08-05 19:41:20 +00:00
|
|
|
{
|
|
|
|
if (file_exception->code() == ENOSPC)
|
2020-08-25 15:06:24 +00:00
|
|
|
{
|
|
|
|
/// See Poco::FileImpl::handleLastErrorImpl(...)
|
|
|
|
constexpr const char * expected_error_message = "no space left on device: ";
|
|
|
|
if (startsWith(file_exception->message(), expected_error_message))
|
|
|
|
{
|
|
|
|
String path = file_exception->message().substr(strlen(expected_error_message));
|
|
|
|
getNoSpaceLeftInfoMessage(path, msg);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
msg += "\nCannot print extra info for Poco::Exception";
|
|
|
|
}
|
|
|
|
}
|
2019-08-05 19:41:20 +00:00
|
|
|
}
|
2020-04-22 05:39:31 +00:00
|
|
|
else if (const auto * errno_exception = dynamic_cast<const DB::ErrnoException *>(&e))
|
2019-08-05 19:41:20 +00:00
|
|
|
{
|
2019-08-06 18:54:06 +00:00
|
|
|
if (errno_exception->getErrno() == ENOSPC && errno_exception->getPath())
|
|
|
|
getNoSpaceLeftInfoMessage(errno_exception->getPath().value(), msg);
|
2020-05-30 19:38:25 +00:00
|
|
|
else if (errno_exception->code() == ErrorCodes::CANNOT_ALLOCATE_MEMORY
|
|
|
|
|| errno_exception->code() == ErrorCodes::CANNOT_MREMAP)
|
|
|
|
getNotEnoughMemoryMessage(msg);
|
|
|
|
}
|
|
|
|
else if (dynamic_cast<const std::bad_alloc *>(&e))
|
|
|
|
{
|
|
|
|
getNotEnoughMemoryMessage(msg);
|
2019-08-05 19:41:20 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-06 20:39:07 +00:00
|
|
|
catch (...)
|
|
|
|
{
|
2019-08-06 14:46:17 +00:00
|
|
|
msg += "\nCannot print extra info: " + getCurrentExceptionMessage(false, false, false);
|
2019-08-05 19:41:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return msg;
|
|
|
|
}
|
|
|
|
|
2019-08-06 12:51:10 +00:00
|
|
|
std::string getCurrentExceptionMessage(bool with_stacktrace, bool check_embedded_stacktrace /*= false*/, bool with_extra_info /*= true*/)
|
2015-06-29 21:35:35 +00:00
|
|
|
{
|
2020-11-10 18:22:26 +00:00
|
|
|
WriteBufferFromOwnString stream;
|
2017-04-01 07:20:54 +00:00
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
catch (const Exception & e)
|
|
|
|
{
|
2019-08-05 19:41:20 +00:00
|
|
|
stream << getExceptionMessage(e, with_stacktrace, check_embedded_stacktrace)
|
2019-08-06 12:51:10 +00:00
|
|
|
<< (with_extra_info ? getExtraExceptionInfo(e) : "")
|
2019-08-05 19:41:20 +00:00
|
|
|
<< " (version " << VERSION_STRING << VERSION_OFFICIAL << ")";
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
catch (const Poco::Exception & e)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2019-04-04 12:34:49 +00:00
|
|
|
stream << "Poco::Exception. Code: " << ErrorCodes::POCO_EXCEPTION << ", e.code() = " << e.code()
|
|
|
|
<< ", e.displayText() = " << e.displayText()
|
Improve stack trace formatting for Poco and std exceptions
Before:
```
<Error> Application: Caught exception while loading metadata: Poco::Exception. Code: 1000, e.code() = 0, e.displayText() = Access to file denied: boo0. /home/nv/clickhouse-master-clion/contrib/poco/Foundation/src/Exception.cpp:27: Poco::FileAccessDeniedException::FileAccessDeniedException(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) @ 0xbb598cc in /state/home/nv/clickhouse-builds/clickhouse-master-clion-gcc/dbms/programs/clickhous
```
After:
```
<Error> Application: Caught exception while loading metadata: Poco::Exception. Code: 1000, e.code() = 0, e.displayText() = Access to file denied: boo, Stack trace (when copying this message, always include the lines below):
0. /home/nv/clickhouse-master-clion/contrib/poco/Foundation/src/Exception.cpp:27: Poco::FileAccessDeniedException::FileAccessDeniedException(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) @ 0xbb5987c in /state/home/nv/clickhouse-builds/clickhouse-master-clion-gcc/dbms/programs/clickhous
```
2020-02-19 13:33:31 +00:00
|
|
|
<< (with_stacktrace ? ", Stack trace (when copying this message, always include the lines below):\n\n" + getExceptionStackTraceString(e) : "")
|
2019-08-06 12:51:10 +00:00
|
|
|
<< (with_extra_info ? getExtraExceptionInfo(e) : "")
|
2020-01-24 02:38:03 +00:00
|
|
|
<< " (version " << VERSION_STRING << VERSION_OFFICIAL << ")";
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
catch (...) {}
|
|
|
|
}
|
|
|
|
catch (const std::exception & e)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
int status = 0;
|
|
|
|
auto name = demangle(typeid(e).name(), status);
|
|
|
|
|
|
|
|
if (status)
|
|
|
|
name += " (demangling status: " + toString(status) + ")";
|
|
|
|
|
2019-08-05 19:41:20 +00:00
|
|
|
stream << "std::exception. Code: " << ErrorCodes::STD_EXCEPTION << ", type: " << name << ", e.what() = " << e.what()
|
Improve stack trace formatting for Poco and std exceptions
Before:
```
<Error> Application: Caught exception while loading metadata: Poco::Exception. Code: 1000, e.code() = 0, e.displayText() = Access to file denied: boo0. /home/nv/clickhouse-master-clion/contrib/poco/Foundation/src/Exception.cpp:27: Poco::FileAccessDeniedException::FileAccessDeniedException(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) @ 0xbb598cc in /state/home/nv/clickhouse-builds/clickhouse-master-clion-gcc/dbms/programs/clickhous
```
After:
```
<Error> Application: Caught exception while loading metadata: Poco::Exception. Code: 1000, e.code() = 0, e.displayText() = Access to file denied: boo, Stack trace (when copying this message, always include the lines below):
0. /home/nv/clickhouse-master-clion/contrib/poco/Foundation/src/Exception.cpp:27: Poco::FileAccessDeniedException::FileAccessDeniedException(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) @ 0xbb5987c in /state/home/nv/clickhouse-builds/clickhouse-master-clion-gcc/dbms/programs/clickhous
```
2020-02-19 13:33:31 +00:00
|
|
|
<< (with_stacktrace ? ", Stack trace (when copying this message, always include the lines below):\n\n" + getExceptionStackTraceString(e) : "")
|
2020-01-02 06:56:53 +00:00
|
|
|
<< (with_extra_info ? getExtraExceptionInfo(e) : "")
|
Improve stack trace formatting for Poco and std exceptions
Before:
```
<Error> Application: Caught exception while loading metadata: Poco::Exception. Code: 1000, e.code() = 0, e.displayText() = Access to file denied: boo0. /home/nv/clickhouse-master-clion/contrib/poco/Foundation/src/Exception.cpp:27: Poco::FileAccessDeniedException::FileAccessDeniedException(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) @ 0xbb598cc in /state/home/nv/clickhouse-builds/clickhouse-master-clion-gcc/dbms/programs/clickhous
```
After:
```
<Error> Application: Caught exception while loading metadata: Poco::Exception. Code: 1000, e.code() = 0, e.displayText() = Access to file denied: boo, Stack trace (when copying this message, always include the lines below):
0. /home/nv/clickhouse-master-clion/contrib/poco/Foundation/src/Exception.cpp:27: Poco::FileAccessDeniedException::FileAccessDeniedException(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) @ 0xbb5987c in /state/home/nv/clickhouse-builds/clickhouse-master-clion-gcc/dbms/programs/clickhous
```
2020-02-19 13:33:31 +00:00
|
|
|
<< " (version " << VERSION_STRING << VERSION_OFFICIAL << ")";
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
catch (...) {}
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
int status = 0;
|
|
|
|
auto name = demangle(abi::__cxa_current_exception_type()->name(), status);
|
|
|
|
|
|
|
|
if (status)
|
|
|
|
name += " (demangling status: " + toString(status) + ")";
|
|
|
|
|
2019-04-04 12:34:49 +00:00
|
|
|
stream << "Unknown exception. Code: " << ErrorCodes::UNKNOWN_EXCEPTION << ", type: " << name << " (version " << VERSION_STRING << VERSION_OFFICIAL << ")";
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
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();
|
|
|
|
}
|
2018-08-10 04:02:56 +00:00
|
|
|
catch (const Poco::Exception &)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
return ErrorCodes::POCO_EXCEPTION;
|
|
|
|
}
|
2018-08-10 04:02:56 +00:00
|
|
|
catch (const std::exception &)
|
2017-04-01 07:20:54 +00:00
|
|
|
{
|
|
|
|
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
|
|
|
{
|
2020-04-22 00:29:38 +00:00
|
|
|
for (const auto & exception : exceptions)
|
2020-03-08 21:04:10 +00:00
|
|
|
if (exception)
|
|
|
|
std::rethrow_exception(exception);
|
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
|
|
|
|
{
|
2020-03-18 03:27:32 +00:00
|
|
|
std::rethrow_exception(std::move(e)); // NOLINT
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
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
|
|
|
|
{
|
2020-03-18 03:27:32 +00:00
|
|
|
std::rethrow_exception(std::move(e)); // NOLINT
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
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)
|
|
|
|
{
|
2020-11-10 18:22:26 +00:00
|
|
|
WriteBufferFromOwnString stream;
|
2017-04-13 16:12:56 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-05 17:02:05 +00:00
|
|
|
stream << "Code: " << e.code() << ", e.displayText() = " << text;
|
2017-04-13 16:12:56 +00:00
|
|
|
|
|
|
|
if (with_stacktrace && !has_embedded_stack_trace)
|
2020-01-02 06:56:53 +00:00
|
|
|
stream << ", Stack trace (when copying this message, always include the lines below):\n\n" << e.getStackTraceString();
|
2017-04-13 16:12:56 +00:00
|
|
|
}
|
|
|
|
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
|
|
|
|
{
|
2020-03-18 03:27:32 +00:00
|
|
|
std::rethrow_exception(std::move(e)); // NOLINT
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
|
|
|
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)
|
|
|
|
{
|
2017-08-02 14:42:35 +00:00
|
|
|
String msg = (start_of_message.empty() ? "" : (start_of_message + ": ")) + getCurrentExceptionMessage(false, true);
|
2017-07-27 18:44:55 +00:00
|
|
|
return ExecutionStatus(getCurrentExceptionCode(), msg);
|
2017-04-27 15:19:11 +00:00
|
|
|
}
|
|
|
|
|
2021-03-03 20:44:51 +00:00
|
|
|
ParsingException::ParsingException() = default;
|
2020-12-18 01:47:24 +00:00
|
|
|
ParsingException::ParsingException(const std::string & msg, int code)
|
2020-12-22 22:33:07 +00:00
|
|
|
: Exception(msg, code)
|
2020-12-18 01:47:24 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
ParsingException::ParsingException(int code, const std::string & message)
|
|
|
|
: Exception(message, code)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/// We use additional field formatted_message_ to make this method const.
|
|
|
|
std::string ParsingException::displayText() const
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
if (line_number_ == -1)
|
2021-03-03 20:44:51 +00:00
|
|
|
formatted_message_ = message();
|
2020-12-18 01:47:24 +00:00
|
|
|
else
|
2021-03-03 20:44:51 +00:00
|
|
|
formatted_message_ = message() + fmt::format(": (at row {})\n", line_number_);
|
2020-12-18 01:47:24 +00:00
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{}
|
|
|
|
|
|
|
|
if (!formatted_message_.empty())
|
|
|
|
{
|
|
|
|
std::string result = name();
|
|
|
|
result.append(": ");
|
|
|
|
result.append(formatted_message_);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return Exception::displayText();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-27 15:19:11 +00:00
|
|
|
|
2010-03-01 16:59:51 +00:00
|
|
|
}
|