Fix possible uncaught exception during distributed query cancellation

Cancellation of distributed queries may throw (i.e. some timeout), and
in case of pipeline had not been properly created properly
(EXCEPTION_BEFORE_START) cancel will not be sent, so cancellation will
be done from dtor and will throw.

<details>

<summary>stacktrace</summary>

```
<Fatal> BaseDaemon: (version 23.9.2.56 (official build), build id: 76109A79FA62B9BC630A6C39438DEA7D28147B68, git hash: a1bf3f1de5) (from thread 51895) Terminate called for uncaught exception:
<Fatal> BaseDaemon: Code: 209. DB::NetException: Timeout exceeded while reading from socket (socket (10.61.1.50:9000), receive timeout 20000 ms). (SOCKET_TIMEOUT), Stack trace (when copying this message, always include the lines below):
<Fatal> BaseDaemon:
<Fatal> BaseDaemon: 0. ./build_docker/./src/Common/Exception.cpp:98: DB::Exception::Exception(DB::Exception::MessageMasked&&, int, bool) @ 0x000000000c741d97 in /usr/lib/debug/usr/bin/clickhouse.debug
<Fatal> BaseDaemon: 1. ./build_docker/./contrib/llvm-project/libcxx/include/string:1499: DB::NetException::NetException<String const&>(int, String const&) @ 0x000000001148ace7 in /usr/lib/debug/usr/bin/clickhouse.debug
<Fatal> BaseDaemon: 2. ./build_docker/./src/QueryPipeline/RemoteQueryExecutorReadContext.cpp:101: DB::RemoteQueryExecutorReadContext::checkTimeout(bool) @ 0x000000001148a70a in /usr/lib/debug/usr/bin/clickhouse.debug
<Fatal> BaseDaemon: 3. ./build_docker/./src/Common/Fiber.h:42: DB::RemoteQueryExecutorReadContext::cancelBefore() @ 0x000000001148aded in /usr/lib/debug/usr/bin/clickhouse.debug
<Fatal> BaseDaemon: 4. ./build_docker/./src/Common/Fiber.h:27: DB::AsyncTaskExecutor::cancel() @ 0x000000001148969d in /usr/lib/debug/usr/bin/clickhouse.debug
<Fatal> BaseDaemon: 5. ./build_docker/./src/QueryPipeline/RemoteQueryExecutor.cpp:169: DB::RemoteQueryExecutor::~RemoteQueryExecutor() @ 0x000000001147a9d0 in /usr/lib/debug/usr/bin/clickhouse.debug
<Fatal> BaseDaemon: 6. ./build_docker/./contrib/llvm-project/libcxx/src/include/atomic_support.h:74: std::__shared_ptr_emplace<DB::RemoteSource, std::allocator<DB::RemoteSource>>::__on_zero_shared() @ 0x000000000c94a4a1 in /usr/lib/debug/usr/bin/clickhou

<Fatal> BaseDaemon: 7. ./build_docker/./contrib/llvm-project/libcxx/src/include/atomic_support.h:74: std::__shared_ptr_emplace<std::vector<std::shared_ptr<DB::IProcessor>, std::allocator<std::shared_ptr<DB::IProcessor>>>, std::allocator<std::vector<std::
or<std::shared_ptr<DB::IProcessor>>>>>::__on_zero_shared() @ 0x00000000114603a1 in /usr/lib/debug/usr/bin/clickhouse.debug
<Fatal> BaseDaemon: 8. ./build_docker/./contrib/llvm-project/libcxx/src/include/atomic_support.h:74: DB::QueryPipeline::~QueryPipeline() @ 0x000000001146347a in /usr/lib/debug/usr/bin/clickhouse.debug
<Fatal> BaseDaemon: 9. ./build_docker/./src/QueryPipeline/QueryPipeline.cpp:709: DB::QueryPipeline::reset() @ 0x0000000011468f78 in /usr/lib/debug/usr/bin/clickhouse.debug
<Fatal> BaseDaemon: 10. ./build_docker/./src/Interpreters/executeQuery.cpp:1427: DB::executeQuery(DB::ReadBuffer&, DB::WriteBuffer&, bool, std::shared_ptr<DB::Context>, std::function<void (DB::QueryResultDetails const&)>, std::optional<DB::FormatSettings> const&, std::function<void (DB::IOutputFormat&)>) @ 0x000000001249aa8b in /usr/lib/debug/usr/bin/clickhouse.debug
<Fatal> BaseDaemon: 11. ./build_docker/./contrib/llvm-project/libcxx/include/__functional/function.h:818: DB::HTTPHandler::processQuery(DB::HTTPServerRequest&, DB::HTMLForm&, DB::HTTPServerResponse&, DB::HTTPHandler::Output&, std::optional<DB::CurrentThread::QueryScope>&) @ 0x00000000132bddb4 in /usr/lib/debug/usr/bin/clickhouse.debug
<Fatal> BaseDaemon: 12. ./build_docker/./contrib/llvm-project/libcxx/include/__memory/unique_ptr.h:290: DB::HTTPHandler::handleRequest(DB::HTTPServerRequest&, DB::HTTPServerResponse&) @ 0x00000000132c23a4 in /usr/lib/debug/usr/bin/clickhouse.debug
```

</details>

Signed-off-by: Azat Khuzhin <a.khuzhin@semrush.com>
This commit is contained in:
Azat Khuzhin 2024-02-01 15:53:13 +01:00
parent 7e77c52c75
commit 3108a988de

View File

@ -182,8 +182,20 @@ RemoteQueryExecutor::~RemoteQueryExecutor()
{
/// Set was_cancelled, so the query won't be sent after creating connections.
was_cancelled = true;
/// Cancellation may throw (i.e. some timeout), and in case of pipeline
/// had not been properly created properly (EXCEPTION_BEFORE_START)
/// cancel will not be sent, so cancellation will be done from dtor and
/// will throw.
try
{
read_context->cancel();
}
catch (...)
{
tryLogCurrentException(log ? log : getLogger("RemoteQueryExecutor"));
}
}
/** If interrupted in the middle of the loop of communication with replicas, then interrupt
* all connections, then read and skip the remaining packets to make sure