Skip to content

Improve the opentelemetry tracing context propagation across threads #39010

Merged
rschu1ze merged 49 commits intoClickHouse:masterfrom
FrankChen021:tracing_context_propagation
Sep 2, 2022
Merged

Improve the opentelemetry tracing context propagation across threads #39010
rschu1ze merged 49 commits intoClickHouse:masterfrom
FrankChen021:tracing_context_propagation

Conversation

@FrankChen021
Copy link
Copy Markdown
Contributor

Changelog category (leave one):

  • Improvement

Changelog entry (a user-readable short description of the changes that goes to CHANGELOG.md):

Improve the tracing context propagation across threads

This PR improves the open-telemetry tracing context propagation to solves some bugs in essence.

Problem 1

Let's take a look at the spans logs for SELECT 1 query, the span logs are ordered by start_time_us and are shown as below

image

From the log we know that:

  1. query is the root span of this tracing
  2. TCPHandler is the child span of the query

However, the TCPHandler is executed in the first place and then query, and also duration of TCPHandler takes longer than the query span. This is totally contradict to what the logs show.

The cause of above problem is that current tracing context initialization depends on ThreadStatus::attachQuery or Context::setCurrentQueryId in HTTPHandler/TCPHandler. However the initialization of context is not used as the root span, the root span is used for the query span which is created at executeQueryImpl which is executed after the setCurrentQueryId.

Problem 2

Another problem caused by current initialization on thread by calling attachQuery is that, for forked threads from HTTPHandler or TCPHandler, this attachQuery it does not correctly get the right parent span but always uses the span info holding at the the Context level.

span.parent_span_id = query_context_ptr->query_trace_context.span_id;

This does not reflect correct parent-child relationship and leads all span logs in child threads to be the child of TCPHandler or HTTPHandler.

Below is an example of INSERT with parallel processing of two MVs.
image

All 3 QueryPushPipeEx threads from the log are looked like forked from query, but in fact, the latter two QueryPushPipeEx are forked by the first QueryPushPipeEx which is forked by TCPHandler thread as shown below
image

Problem 3

Relying on attachQuery to build context on one thread is not always the right choice. Another example is for async processing of distributed table insert. These async insert are performed in background threads, it has no query context to attach to the threads that executes the async processing. So the span logs of async processing can't be logged. A previous PR raised by me only solves the link span logs on two nodes, but has no ability to add span logs on one node starting from async processing. This would lose some key information if the async processing fails.

Root Cause

The root cause is that current implementation uses different variables to hold tracing context, one is Context:: query_trace_context and the other is ThreadStatus::thread_trace_context. The span logs created by OpenTelemetrySpanHolder are initialised from the latter one, however thread level context is initialised from the former one. This causes the chaos.

Solution

The rationale of the solution is simple, just keep one thread-local variable to hold tracing context on current thread, when a child thread is forked, the parent thread is responsible to copy the tracing context to the child thread.
This method is a common and widely used by other tracing propagation tools on Java platform.

Changes

  1. tracing context processing is now independent on ThreadStatus, and all codes are put into a separated file OpenTelemetryTraceContext.cpp
  2. A new class OpenTelemetryThreadTraceContext is created to hold the context on one thread, it mainly holds the trace_id, current span_id and a weak reference to the system table opentelemetry_span_log. It should be initialized at the beginning execution of one thread.
  3. a new thread-local variable current_thread_trace_context is defined and public static method OpenTelemetryThreadTraceContext::current is provided to access context on current thread
  4. tracing context is copied from parent thread to sub-thread when a task/job is forked to maintain correct parent-child span log relationship, see changes in ThreadPool.cpp
  5. For each starting point of query execution, such as HTTP, TCP and GRPCServer, tracing context is initialized on current thread
  6. For async distributed table insert, tracing context is re-initialized on threads to ensure the context propgation(See changes in DirectoryMonitor.cpp). Also there're some improvements on the span logs in the following processing(See Connection.cpp and RemoteInserter.cpp, DistributedSink.cpp ).
  7. A useless span InterpreterFactory::get() is removed
  8. (A bug fix) query level span log is correctly recorded if an exception is thrown, see executeQuery.cpp

Other Info

This patch has been running on our clusters(based on 21.8.4) for more than half a year, all changes proves to be correct.

@FrankChen021
Copy link
Copy Markdown
Contributor Author

There might be conflicts once #38965 is merged

@robot-ch-test-poll1 robot-ch-test-poll1 added the pr-improvement Pull request with some product improvements label Jul 8, 2022
@qoega qoega added the can be tested Allows running workflows for external contributors label Jul 8, 2022
@qoega
Copy link
Copy Markdown
Member

qoega commented Jul 8, 2022

There might be conflicts once #38965 is merged

No worries. Your PR if merged will make that one irrelevant.

@qoega
Copy link
Copy Markdown
Member

qoega commented Jul 12, 2022

This PR fixes #39122?

@FrankChen021

This comment was marked as outdated.

@qoega

This comment was marked as outdated.

@FrankChen021

This comment was marked as outdated.

Signed-off-by: Frank Chen <[email protected]>
@rschu1ze
Copy link
Copy Markdown
Member

rschu1ze commented Sep 1, 2022

Thanks.

In the tests which finished already, there is still a problem


2022.09.01 02:09:39.402170 [ 9619 ] {} <Fatal> BaseDaemon: ########################################
2022.09.01 02:09:39.402537 [ 9619 ] {} <Fatal> BaseDaemon: (version 22.9.1.1, build id: 5B87666C4CEF30DEE6F229DBF2D6F09E1F80E008) (from thread 7278) (query_id: 36588d4d-114d-4c84-a816-441905b58e29) (query: SHOW TABLES FROM test_01889_sqllite_test_svjhaf;) Received signal Aborted (6)
2022.09.01 02:09:39.402740 [ 9619 ] {} <Fatal> BaseDaemon: 
2022.09.01 02:09:39.402936 [ 9619 ] {} <Fatal> BaseDaemon: Stack trace: 0x7f162167000b 0x7f162164f859 0x7f162164f729 0x7f1621660fd6 0x1738ec04 0x1738ee79 0x2769a253 0x2769a13c 0x27696a39 0x276851ba 0x276819a4 0x287751d8 0x28785525 0x2cdc1ab9 0x2cdc231c 0x2d00fa54 0x2d00c51a 0x2d00b2be 0x7f1621827609 0x7f162174c133
2022.09.01 02:09:39.403200 [ 9619 ] {} <Fatal> BaseDaemon: 4. gsignal @ 0x7f162167000b in ?
2022.09.01 02:09:39.403427 [ 9619 ] {} <Fatal> BaseDaemon: 5. abort @ 0x7f162164f859 in ?
2022.09.01 02:09:39.403582 [ 9619 ] {} <Fatal> BaseDaemon: 6. ? @ 0x7f162164f729 in ?
2022.09.01 02:09:39.403797 [ 9619 ] {} <Fatal> BaseDaemon: 7. ? @ 0x7f1621660fd6 in ?
2022.09.01 02:09:39.478951 [ 9619 ] {} <Fatal> BaseDaemon: 8. /build/build_docker/../src/Common/OpenTelemetryTraceContext.cpp:0: DB::OpenTelemetry::SpanHolder::finish() @ 0x1738ec04 in /usr/bin/clickhouse
2022.09.01 02:09:39.554175 [ 9619 ] {} <Fatal> BaseDaemon: 9. /build/build_docker/../src/Common/OpenTelemetryTraceContext.cpp:138: DB::OpenTelemetry::SpanHolder::~SpanHolder() @ 0x1738ee79 in /usr/bin/clickhouse
2022.09.01 02:09:40.015265 [ 9619 ] {} <Fatal> BaseDaemon: 10. /build/build_docker/../contrib/libcxx/include/__memory/unique_ptr.h:54: std::__1::default_delete<DB::OpenTelemetry::SpanHolder>::operator()(DB::OpenTelemetry::SpanHolder*) const @ 0x2769a253 in /usr/bin/clickhouse
2022.09.01 02:09:40.427360 [ 9619 ] {} <Fatal> BaseDaemon: 11. /build/build_docker/../contrib/libcxx/include/__memory/unique_ptr.h:316: std::__1::unique_ptr<DB::OpenTelemetry::SpanHolder, std::__1::default_delete<DB::OpenTelemetry::SpanHolder> >::reset(DB::OpenTelemetry::SpanHolder*) @ 0x2769a13c in /usr/bin/clickhouse
2022.09.01 02:09:40.936962 [ 9619 ] {} <Fatal> BaseDaemon: 12. /build/build_docker/../contrib/libcxx/include/__memory/unique_ptr.h:269: std::__1::unique_ptr<DB::OpenTelemetry::SpanHolder, std::__1::default_delete<DB::OpenTelemetry::SpanHolder> >::~unique_ptr() @ 0x27696a39 in /usr/bin/clickhouse
2022.09.01 02:09:41.486400 [ 9619 ] {} <Fatal> BaseDaemon: 13. /build/build_docker/../src/Interpreters/executeQuery.cpp:678: DB::executeQueryImpl(char const*, char const*, std::__1::shared_ptr<DB::Context>, bool, DB::QueryProcessingStage::Enum, DB::ReadBuffer*) @ 0x276851ba in /usr/bin/clickhouse
2022.09.01 02:09:41.883240 [ 9619 ] {} <Fatal> BaseDaemon: 14. /build/build_docker/../src/Interpreters/executeQuery.cpp:1072: DB::executeQuery(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::shared_ptr<DB::Context>, bool, DB::QueryProcessingStage::Enum) @ 0x276819a4 in /usr/bin/clickhouse
2022.09.01 02:09:42.349239 [ 9619 ] {} <Fatal> BaseDaemon: 15. /build/build_docker/../src/Server/TCPHandler.cpp:362: DB::TCPHandler::runImpl() @ 0x287751d8 in /usr/bin/clickhouse
2022.09.01 02:09:42.895858 [ 9619 ] {} <Fatal> BaseDaemon: 16. /build/build_docker/../src/Server/TCPHandler.cpp:1879: DB::TCPHandler::run() @ 0x28785525 in /usr/bin/clickhouse
2022.09.01 02:09:42.976379 [ 9619 ] {} <Fatal> BaseDaemon: 17. /build/build_docker/../contrib/poco/Net/src/TCPServerConnection.cpp:43: Poco::Net::TCPServerConnection::start() @ 0x2cdc1ab9 in /usr/bin/clickhouse
2022.09.01 02:09:43.080484 [ 9619 ] {} <Fatal> BaseDaemon: 18. /build/build_docker/../contrib/poco/Net/src/TCPServerDispatcher.cpp:115: Poco::Net::TCPServerDispatcher::run() @ 0x2cdc231c in /usr/bin/clickhouse
2022.09.01 02:09:43.200644 [ 9619 ] {} <Fatal> BaseDaemon: 19. /build/build_docker/../contrib/poco/Foundation/src/ThreadPool.cpp:199: Poco::PooledThread::run() @ 0x2d00fa54 in /usr/bin/clickhouse
2022.09.01 02:09:43.305014 [ 9619 ] {} <Fatal> BaseDaemon: 20. /build/build_docker/../contrib/poco/Foundation/src/Thread.cpp:56: Poco::(anonymous namespace)::RunnableHolder::run() @ 0x2d00c51a in /usr/bin/clickhouse
2022.09.01 02:09:43.411116 [ 9619 ] {} <Fatal> BaseDaemon: 21. /build/build_docker/../contrib/poco/Foundation/src/Thread_POSIX.cpp:345: Poco::ThreadImpl::runnableEntry(void*) @ 0x2d00b2be in /usr/bin/clickhouse
2022.09.01 02:09:43.411373 [ 9619 ] {} <Fatal> BaseDaemon: 22. ? @ 0x7f1621827609 in ?
2022.09.01 02:09:43.411566 [ 9619 ] {} <Fatal> BaseDaemon: 23. __clone @ 0x7f162174c133 in ?
2022.09.01 02:09:44.722480 [ 9619 ] {} <Fatal> BaseDaemon: Integrity check of the executable skipped because the reference checksum could not be read. (calculated checksum: A492D883FD7D7F8DECE8F4090D9F810F)
2022.09.01 02:09:59.865357 [ 633 ] {} <Fatal> Application: Child process was terminated by signal 6.

Would you like to take a look?

@FrankChen021
Copy link
Copy Markdown
Contributor Author

Hi @rschu1ze I noticed this problem.

It's a little bit strange why the assert works. Do you know how to run such test on local to reproduce it?

@rschu1ze
Copy link
Copy Markdown
Member

rschu1ze commented Sep 1, 2022

To run one of the failing stateless test, 1. compile a debug build and 2. follow the steps described here, e.g. PATH=$PATH:build/programs/ tests/clickhouse-test 01428_hash_set_nan_key

@FrankChen021
Copy link
Copy Markdown
Contributor Author

This problem was due to recursive calls of executeQuery of some queries like 'show xxx'. We didn't notice this problem on our branch for a very long time because we always run release version. For fix this problem, spans in nested call of executeQuery are disabled.

@rschu1ze rschu1ze merged commit 319d8b0 into ClickHouse:master Sep 2, 2022
@FrankChen021
Copy link
Copy Markdown
Contributor Author

Thank you @rschu1ze for your detailed review comments. It's a nice journey to work with you on this PR.

@FrankChen021 FrankChen021 deleted the tracing_context_propagation branch September 2, 2022 06:21
@rschu1ze
Copy link
Copy Markdown
Member

rschu1ze commented Sep 2, 2022

My pleasure 😉

@tavplubix
Copy link
Copy Markdown
Member

Seems like some exception safety issues are still there:
https://s3.amazonaws.com/clickhouse-test-reports/0/3a0581e99034c1e985b4e799f16d04baf3cbf037/stress_test__ubsan_.html

/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.076003 [ 62969 ] {} <Fatal> BaseDaemon: ########################################
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.076398 [ 62969 ] {} <Fatal> BaseDaemon: (version 22.9.1.1 (official build), build id: E50B79A7E4DEC9F5D5D7932C615AA5F3E8D51C25) (from thread 3780) (query_id: 40990c85-df63-4bb8-a8f4-ba5b9d325ff9) (query: SELECT count() FROM test.merge_hits PREWHERE AdvEngineID = 2;) Received signal Aborted (6)
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.090899 [ 62969 ] {} <Fatal> BaseDaemon: 
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.091623 [ 62969 ] {} <Fatal> BaseDaemon: Stack trace: 0x7f6d32b6900b 0x7f6d32b48859 0x2707668a 0x2709091a 0x27ff6eac 0x27ff739a 0x2816f087 0x2816cb6f 0x7f6d32d20609 0x7f6d32c45133
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.092070 [ 62969 ] {} <Fatal> BaseDaemon: 3. raise @ 0x7f6d32b6900b in ?
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.092660 [ 62969 ] {} <Fatal> BaseDaemon: 4. abort @ 0x7f6d32b48859 in ?
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.131836 [ 62969 ] {} <Fatal> BaseDaemon: 5. ./build_docker/../src/Server/TCPHandler.cpp:477: DB::TCPHandler::runImpl() @ 0x2707668a in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.482294 [ 62969 ] {} <Fatal> BaseDaemon: 6. ./build_docker/../src/Server/TCPHandler.cpp:1881: DB::TCPHandler::run() @ 0x2709091a in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.486332 [ 62969 ] {} <Fatal> BaseDaemon: 7. ./build_docker/../contrib/poco/Net/src/TCPServerConnection.cpp:57: Poco::Net::TCPServerConnection::start() @ 0x27ff6eac in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.492493 [ 62969 ] {} <Fatal> BaseDaemon: 8.1. inlined from ./build_docker/../contrib/libcxx/include/__memory/unique_ptr.h:54: std::__1::default_delete<Poco::Net::TCPServerConnection>::operator()(Poco::Net::TCPServerConnection*) const
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.501389 [ 62969 ] {} <Fatal> BaseDaemon: 8.2. inlined from ../contrib/libcxx/include/__memory/unique_ptr.h:315: std::__1::unique_ptr<Poco::Net::TCPServerConnection, std::__1::default_delete<Poco::Net::TCPServerConnection> >::reset(Poco::Net::TCPServerConnection*)
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.502165 [ 62969 ] {} <Fatal> BaseDaemon: 8.3. inlined from ../contrib/libcxx/include/__memory/unique_ptr.h:269: ~unique_ptr
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.502582 [ 62969 ] {} <Fatal> BaseDaemon: 8. ../contrib/poco/Net/src/TCPServerDispatcher.cpp:116: Poco::Net::TCPServerDispatcher::run() @ 0x27ff739a in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.524799 [ 62969 ] {} <Fatal> BaseDaemon: 9. ./build_docker/../contrib/poco/Foundation/src/ThreadPool.cpp:213: Poco::PooledThread::run() @ 0x2816f087 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.732272 [ 62969 ] {} <Fatal> BaseDaemon: 10.1. inlined from ./build_docker/../contrib/poco/Foundation/include/Poco/SharedPtr.h:156: Poco::SharedPtr<Poco::Runnable, Poco::ReferenceCounter, Poco::ReleasePolicy<Poco::Runnable> >::assign(Poco::Runnable*)
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.737469 [ 62969 ] {} <Fatal> BaseDaemon: 10.2. inlined from ../contrib/poco/Foundation/include/Poco/SharedPtr.h:208: Poco::SharedPtr<Poco::Runnable, Poco::ReferenceCounter, Poco::ReleasePolicy<Poco::Runnable> >::operator=(Poco::Runnable*)
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.739109 [ 62969 ] {} <Fatal> BaseDaemon: 10. ../contrib/poco/Foundation/src/Thread_POSIX.cpp:360: Poco::ThreadImpl::runnableEntry(void*) @ 0x2816cb6f in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.741181 [ 62969 ] {} <Fatal> BaseDaemon: 11. ? @ 0x7f6d32d20609 in ?
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.741938 [ 62969 ] {} <Fatal> BaseDaemon: 12. clone @ 0x7f6d32c45133 in ?
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.956059 [ 651 ] {} <Fatal> BaseDaemon: (version 22.9.1.1 (official build), build id: E50B79A7E4DEC9F5D5D7932C615AA5F3E8D51C25) (from thread 21045) Terminate called for uncaught exception:
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:35.996010 [ 651 ] {} <Fatal> BaseDaemon: Code: 241. DB::Exception: Memory limit (total) exceeded: would use 51.85 GiB (attempt to allocate chunk of 112 bytes), maximum: 51.44 GiB. OvercommitTracker decision: Memory overcommit isn't used. OvercommitTracker isn't set. (MEMORY_LIMIT_EXCEEDED), Stack trace (when copying this message, always include the lines below):
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.017924 [ 651 ] {} <Fatal> BaseDaemon: 
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.025210 [ 651 ] {} <Fatal> BaseDaemon: 0. ./build_docker/../contrib/libcxx/include/exception:133: Poco::Exception::Exception(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) @ 0x2810a052 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.037926 [ 651 ] {} <Fatal> BaseDaemon: 1. ./build_docker/../src/Common/Exception.cpp:69: DB::Exception::Exception(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int, bool) @ 0x1031942f in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.056901 [ 651 ] {} <Fatal> BaseDaemon: 2. ./build_docker/../contrib/libcxx/include/string:1445: DB::Exception::Exception<char const*, char const*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, long&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string_view<char, std::__1::char_traits<char> > >(int, fmt::v8::basic_format_string<char, fmt::v8::type_identity<char const*>::type, fmt::v8::type_identity<char const*>::type, fmt::v8::type_identity<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::type, fmt::v8::type_identity<long&>::type, fmt::v8::type_identity<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >::type, fmt::v8::type_identity<std::__1::basic_string_view<char, std::__1::char_traits<char> > >::type>, char const*&&, char const*&&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, long&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >&&, std::__1::basic_string_view<char, std::__1::char_traits<char> >&&) @ 0x102fb699 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.061349 [ 651 ] {} <Fatal> BaseDaemon: 3. ./build_docker/../src/Common/MemoryTracker.cpp:232: MemoryTracker::allocImpl(long, bool, MemoryTracker*) @ 0x102faac7 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.092471 [ 651 ] {} <Fatal> BaseDaemon: 4. ./build_docker/../src/Common/AllocatorWithMemoryTracking.h:35: DB::OpenTelemetry::Span::addAttribute(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned long) @ 0x103ec3c8 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.130338 [ 651 ] {} <Fatal> BaseDaemon: 5. ./build_docker/../src/Common/OpenTelemetryTraceContext.cpp:0: DB::OpenTelemetry::TracingContextHolder::TracingContextHolder(std::__1::basic_string_view<char, std::__1::char_traits<char> >, DB::OpenTelemetry::TracingContext, DB::Settings const*, std::__1::weak_ptr<DB::OpenTelemetrySpanLog> const&) @ 0x103ee782 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.161810 [ 651 ] {} <Fatal> BaseDaemon: 6. ./build_docker/../contrib/libcxx/include/string:1445: DB::OpenTelemetry::TracingContextHolder::TracingContextHolder(std::__1::basic_string_view<char, std::__1::char_traits<char> >, DB::OpenTelemetry::TracingContextOnThread const&) @ 0x103e4bf7 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.180810 [ 651 ] {} <Fatal> BaseDaemon: 7. ./build_docker/../src/Common/CurrentMetrics.h:76: ThreadPoolImpl<std::__1::thread>::worker(std::__1::__list_iterator<std::__1::thread, void*>) @ 0x103e44c4 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.208206 [ 651 ] {} <Fatal> BaseDaemon: 8. ./build_docker/../src/Common/ThreadPool.cpp:0: void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void ThreadPoolImpl<std::__1::thread>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>, bool)::'lambda0'()> >(void*) @ 0x103e7e03 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.320530 [ 651 ] {} <Fatal> BaseDaemon: 9. ? @ 0x7f6d32d20609 in ?
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.353922 [ 651 ] {} <Fatal> BaseDaemon: 10. clone @ 0x7f6d32c45133 in ?
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.547448 [ 62969 ] {} <Fatal> BaseDaemon: Integrity check of the executable successfully passed (checksum: A6DDD77C14043933E2DE61BAF214FDBF)
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.470675 [ 651 ] {} <Fatal> BaseDaemon:  (version 22.9.1.1 (official build))
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.699649 [ 63029 ] {} <Fatal> BaseDaemon: ########################################
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.699829 [ 63029 ] {} <Fatal> BaseDaemon: (version 22.9.1.1 (official build), build id: E50B79A7E4DEC9F5D5D7932C615AA5F3E8D51C25) (from thread 21045) (no query) Received signal Aborted (6)
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.699999 [ 63029 ] {} <Fatal> BaseDaemon: 
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.700179 [ 63029 ] {} <Fatal> BaseDaemon: Stack trace: 0x7f6d32b6900b 0x7f6d32b48859 0x105fa2ff 0x2a607d88 0x2a6073bb 0x2a607335 0x102faae0 0x103ec3c8 0x103ee782 0x103e4bf7 0x103e44c4 0x103e7e03 0x7f6d32d20609 0x7f6d32c45133
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.700395 [ 63029 ] {} <Fatal> BaseDaemon: 3. raise @ 0x7f6d32b6900b in ?
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.700597 [ 63029 ] {} <Fatal> BaseDaemon: 4. abort @ 0x7f6d32b48859 in ?
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.709567 [ 63029 ] {} <Fatal> BaseDaemon: 5. ./build_docker/../src/Daemon/BaseDaemon.cpp:464: terminate_handler() @ 0x105fa2ff in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.713482 [ 63029 ] {} <Fatal> BaseDaemon: 6. ./build_docker/../contrib/libcxxabi/src/cxa_handlers.cpp:61: std::__terminate(void (*)()) @ 0x2a607d88 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.718950 [ 63029 ] {} <Fatal> BaseDaemon: 7. ./build_docker/../contrib/libcxxabi/src/cxa_exception.cpp:152: ? @ 0x2a6073bb in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.723821 [ 63029 ] {} <Fatal> BaseDaemon: 8. ./build_docker/../contrib/libcxxabi/src/cxa_exception.cpp:283: ? @ 0x2a607335 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.736628 [ 63029 ] {} <Fatal> BaseDaemon: 9. ./build_docker/../src/Common/MemoryTracker.cpp:127: MemoryTracker::allocImpl(long, bool, MemoryTracker*) @ 0x102faae0 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.742416 [ 63029 ] {} <Fatal> BaseDaemon: 10.1. inlined from ./build_docker/../src/Common/AllocatorWithMemoryTracking.h:35: AllocatorWithMemoryTracking<DB::Field>::allocate(unsigned long)
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.746994 [ 63029 ] {} <Fatal> BaseDaemon: 10.2. inlined from ../contrib/libcxx/include/__memory/allocator_traits.h:262: std::__1::allocator_traits<AllocatorWithMemoryTracking<DB::Field> >::allocate(AllocatorWithMemoryTracking<DB::Field>&, unsigned long)
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.747180 [ 63029 ] {} <Fatal> BaseDaemon: 10.3. inlined from ../contrib/libcxx/include/vector:922: std::__1::vector<DB::Field, AllocatorWithMemoryTracking<DB::Field> >::__vallocate(unsigned long)
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.747344 [ 63029 ] {} <Fatal> BaseDaemon: 10.4. inlined from ../contrib/libcxx/include/vector:1227: vector
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.747506 [ 63029 ] {} <Fatal> BaseDaemon: 10.5. inlined from ../src/Core/Field.h:50: vector
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.748704 [ 63029 ] {} <Fatal> BaseDaemon: 10. ../src/Common/OpenTelemetryTraceContext.cpp:22: DB::OpenTelemetry::Span::addAttribute(std::__1::basic_string_view<char, std::__1::char_traits<char> >, unsigned long) @ 0x103ec3c8 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.756091 [ 63029 ] {} <Fatal> BaseDaemon: 11.1. inlined from ./build_docker/../src/Common/OpenTelemetryTraceContext.cpp:0: __tls_init
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.756260 [ 63029 ] {} <Fatal> BaseDaemon: 11. ../src/Common/OpenTelemetryTraceContext.cpp:291: DB::OpenTelemetry::TracingContextHolder::TracingContextHolder(std::__1::basic_string_view<char, std::__1::char_traits<char> >, DB::OpenTelemetry::TracingContext, DB::Settings const*, std::__1::weak_ptr<DB::OpenTelemetrySpanLog> const&) @ 0x103ee782 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.767946 [ 63029 ] {} <Fatal> BaseDaemon: 12.1. inlined from ./build_docker/../contrib/libcxx/include/string:1445: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__is_long() const
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.768211 [ 63029 ] {} <Fatal> BaseDaemon: 12.2. inlined from ../contrib/libcxx/include/string:2231: ~basic_string
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.768371 [ 63029 ] {} <Fatal> BaseDaemon: 12.3. inlined from ../src/Common/OpenTelemetryTraceContext.h:49: ~TracingContext
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.768530 [ 63029 ] {} <Fatal> BaseDaemon: 12. ../src/Common/OpenTelemetryTraceContext.h:112: DB::OpenTelemetry::TracingContextHolder::TracingContextHolder(std::__1::basic_string_view<char, std::__1::char_traits<char> >, DB::OpenTelemetry::TracingContextOnThread const&) @ 0x103e4bf7 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.778921 [ 63029 ] {} <Fatal> BaseDaemon: 13.1. inlined from ./build_docker/../src/Common/CurrentMetrics.h:76: Increment
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.779135 [ 63029 ] {} <Fatal> BaseDaemon: 13. ../src/Common/ThreadPool.cpp:291: ThreadPoolImpl<std::__1::thread>::worker(std::__1::__list_iterator<std::__1::thread, void*>) @ 0x103e44c4 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.891776 [ 63029 ] {} <Fatal> BaseDaemon: 14. ./build_docker/../src/Common/ThreadPool.cpp:0: void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void ThreadPoolImpl<std::__1::thread>::scheduleImpl<void>(std::__1::function<void ()>, int, std::__1::optional<unsigned long>, bool)::'lambda0'()> >(void*) @ 0x103e7e03 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.891970 [ 63029 ] {} <Fatal> BaseDaemon: 15. ? @ 0x7f6d32d20609 in ?
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.892122 [ 63029 ] {} <Fatal> BaseDaemon: 16. clone @ 0x7f6d32c45133 in ?
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:37.893328 [ 63029 ] {} <Fatal> BaseDaemon: Integrity check of the executable successfully passed (checksum: A6DDD77C14043933E2DE61BAF214FDBF)

@rschu1ze
Copy link
Copy Markdown
Member

rschu1ze commented Sep 6, 2022

The line numbers in the stack are a bit strange. @FrankChen021 Do you have an idea what could be the cause for the issues? (had a quick look but couldn't find an obvious error)

@FrankChen021
Copy link
Copy Markdown
Contributor Author

The line numbers in the stack are a bit strange. @FrankChen021 Do you have an idea what could be the cause for the issues? (had a quick look but couldn't find an obvious error)

Sorry, I didn't notice the comment, let me check.

@qoega
Copy link
Copy Markdown
Member

qoega commented Sep 6, 2022

In stress tests we have fail injection with some probability for all allocations. To check that we are exception safe with bad_alloc. Previously we had issue with addAttributes when it used two arrays instead of a map.
Maybe it is noexcept + bad_alloc now?

@FrankChen021
Copy link
Copy Markdown
Contributor Author

Is the exception thrown because of memory limit?

<Fatal> BaseDaemon: Code: 241. DB::Exception: Memory limit (total) exceeded: would use 51.85 GiB (attempt to allocate chunk of 112 bytes), maximum: 51.44 GiB. OvercommitTracker decision: Memory overcommit isn't used. OvercommitTracker isn't set. (MEMORY_LIMIT_EXCEEDED), Stack trace (when copying this message, always include the lines below):
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.017924 [ 651 ] {} <Fatal> BaseDaemon: 
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.05 11:36:36.025210 [ 651 ] {} <Fatal> BaseDaemon: 0. ./build_docker/../contrib/libcxx/include/exception:133: Poco::Exception::Exception(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) @ 0x2810a052 in /usr/bin/clickhouse

@FrankChen021
Copy link
Copy Markdown
Contributor Author

DB::OpenTelemetry::TracingContextHolder thread_trace_context("ThreadPool::worker()", parent_thead_trace_context);

I got why it crashes. The exception is thrown during the construction, but the construction is out of a try-catch scope.

There was a try-catch around the addAttributed call in the ctor, but as suggested by the comment: #39010 (comment)
It's was remove in a later commit.

I'm thinking revert the change, to move the call of addAttribute from ctor to dtor, and add a try-catch around the addAttribute in the dtor, so that both ctor and dtor are exception safe.

Does this make sense? @rschu1ze

@rschu1ze
Copy link
Copy Markdown
Member

rschu1ze commented Sep 6, 2022

Let me note that the issue in #39010 (comment) happens in an ubsan build but doesn't look like undefined behavior. For undefined behavior, I'd expect some ::Die() call somewhere in the stack. We simply hit the max allocation limit.

So an exception was thrown during addAttribute() in the ctor of TracingContextHolder. And yes, prior to #39010 (comment), that exception was swallowed.

Code in "Common/ThreadPool.cpp":

DENY_ALLOCATIONS_IN_SCOPE;
...
ALLOW_ALLOCATIONS_IN_SCOPE;
DB::OpenTelemetry::TracingContextHolder thread_trace_context("ThreadPool::worker()", parent_thead_trace_context);
try {
    ...
}
catch(...)
{
    ...
}

So allocations below the inner allocation scope are generally allowed but they may still fail, like here. In theory, no bad things should happen. But if you look at the code prior to this PR, you find that exceptions could only be thrown from the try block and the catch block was doing cleanup. An exception from TracingContextHolder doesn't go into the catch.

So: The suggestion would be to check carefully that the ctor of TracingContextHolder doesn't throw any exceptions, including but not limited to bad_alloc. And maybe also add a source code comment about that to the ctor to safeguard future commits.

@FrankChen021
Copy link
Copy Markdown
Contributor Author

So: The suggestion would be to check carefully that the ctor of TracingContextHolder doesn't throw any exceptions, including but not limited to bad_alloc. And maybe also add a source code comment about that to the ctor to safeguard future commits.

Yes, that's why I move the addAttribute to dtor in the hope that the code in the ctor are simple and won't throw exceptions. But according to your comment in the my later PR, seems that we can't ensure these codes in the ctor are safe, and the only way is to add a try-catch.

@qoega
Copy link
Copy Markdown
Member

qoega commented Sep 12, 2022

@FrankChen021 There is one more failure in stress test.

clickhouse-server: ../src/Common/OpenTelemetryTraceContext.cpp:127: void DB::OpenTelemetry::SpanHolder::finish(): Assertion `current_thread_trace_context.span_id == span_id' failed.
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:01.008066 [ 176653 ] {} <Fatal> BaseDaemon: ########################################
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:01.030039 [ 176653 ] {} <Fatal> BaseDaemon: (version 22.9.1.1 (official build), build id: B40BCF1617D6BF84C468A76794E1409DD7D99DB9) (from thread 3274) (no query) Received signal Aborted (6)
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:01.088743 [ 176653 ] {} <Fatal> BaseDaemon: 
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:01.126746 [ 176653 ] {} <Fatal> BaseDaemon: Stack trace: 0x7f7f8a6ee00b 0x7f7f8a6cd859 0x7f7f8a6cd729 0x7f7f8a6defd6 0x173f05e4 0x173f0859 0x27709020 0x27708fb5 0x27708f99 0x27708dae 0x172e62d4 0x172e6279 0x2770874c 0x277015c0 0x27706a95 0x27706a35 0x27706835 0x17323845 0x17323781 0x1731fb6d 0x2606923d 0x288449c6 0x288438ac 0x2882bd2a 0x2882c0b9 0x2ce9ca34 0x2ce9c99c 0x2ce9c559 0x2ce9ba6e 0x2d0e9194 0x2d0e5c5a 0x2d0e49fe 0x7f7f8a8a5609 0x7f7f8a7ca133
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:01.146506 [ 176653 ] {} <Fatal> BaseDaemon: 4. raise @ 0x7f7f8a6ee00b in ?
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:01.173447 [ 176653 ] {} <Fatal> BaseDaemon: 5. abort @ 0x7f7f8a6cd859 in ?
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:01.182271 [ 176653 ] {} <Fatal> BaseDaemon: 6. ? @ 0x7f7f8a6cd729 in ?
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:01.195840 [ 176653 ] {} <Fatal> BaseDaemon: 7. ? @ 0x7f7f8a6defd6 in ?
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:01.354724 [ 176653 ] {} <Fatal> BaseDaemon: 8. /build/build_docker/../src/Common/OpenTelemetryTraceContext.cpp:0: DB::OpenTelemetry::SpanHolder::finish() @ 0x173f05e4 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:01.963284 [ 176653 ] {} <Fatal> BaseDaemon: 9. /build/build_docker/../src/Common/OpenTelemetryTraceContext.cpp:154: DB::OpenTelemetry::SpanHolder::~SpanHolder() @ 0x173f0859 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:03.492253 [ 176653 ] {} <Fatal> BaseDaemon: 10. /build/build_docker/../contrib/libcxx/include/__memory/construct_at.h:57: void std::__1::__destroy_at<DB::OpenTelemetry::SpanHolder, 0>(DB::OpenTelemetry::SpanHolder*) @ 0x27709020 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:04.722439 [ 176653 ] {} <Fatal> BaseDaemon: 11. /build/build_docker/../contrib/libcxx/include/__memory/construct_at.h:82: void std::__1::destroy_at<DB::OpenTelemetry::SpanHolder, 0>(DB::OpenTelemetry::SpanHolder*) @ 0x27708fb5 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:05.888681 [ 176653 ] {} <Fatal> BaseDaemon: 12. /build/build_docker/../contrib/libcxx/include/__memory/allocator_traits.h:321: void std::__1::allocator_traits<std::__1::allocator<DB::OpenTelemetry::SpanHolder> >::destroy<DB::OpenTelemetry::SpanHolder, void, void>(std::__1::allocator<DB::OpenTelemetry::SpanHolder>&, DB::OpenTelemetry::SpanHolder*) @ 0x27708f99 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:06.767503 [ 176653 ] {} <Fatal> BaseDaemon: 13. /build/build_docker/../contrib/libcxx/include/__memory/shared_ptr.h:310: std::__1::__shared_ptr_emplace<DB::OpenTelemetry::SpanHolder, std::__1::allocator<DB::OpenTelemetry::SpanHolder> >::__on_zero_shared() @ 0x27708dae in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:07.279442 [ 176653 ] {} <Fatal> BaseDaemon: 14. /build/build_docker/../contrib/libcxx/include/__memory/shared_ptr.h:175: std::__1::__shared_count::__release_shared() @ 0x172e62d4 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:07.448494 [ 176653 ] {} <Fatal> BaseDaemon: 15. /build/build_docker/../contrib/libcxx/include/__memory/shared_ptr.h:216: std::__1::__shared_weak_count::__release_shared() @ 0x172e6279 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:08.222220 [ 176653 ] {} <Fatal> BaseDaemon: 16. /build/build_docker/../contrib/libcxx/include/__memory/shared_ptr.h:704: std::__1::shared_ptr<DB::OpenTelemetry::SpanHolder>::~shared_ptr() @ 0x2770874c in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:09.046296 [ 176653 ] {} <Fatal> BaseDaemon: 17. /build/build_docker/../src/Interpreters/executeQuery.cpp:971: DB::executeQueryImpl(char const*, char const*, std::__1::shared_ptr<DB::Context>, bool, DB::QueryProcessingStage::Enum, DB::ReadBuffer*)::$_1::~$_1() @ 0x277015c0 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:10.380186 [ 176653 ] {} <Fatal> BaseDaemon: 18. /build/build_docker/../contrib/libcxx/include/__functional/function.h:244: std::__1::__function::__default_alloc_func<DB::executeQueryImpl(char const*, char const*, std::__1::shared_ptr<DB::Context>, bool, DB::QueryProcessingStage::Enum, DB::ReadBuffer*)::$_1, void ()>::destroy() @ 0x27706a95 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:13.896046 [ 176653 ] {} <Fatal> BaseDaemon: 19. /build/build_docker/../contrib/libcxx/include/__functional/function.h:248: std::__1::__function::__default_alloc_func<DB::executeQueryImpl(char const*, char const*, std::__1::shared_ptr<DB::Context>, bool, DB::QueryProcessingStage::Enum, DB::ReadBuffer*)::$_1, void ()>::__destroy_and_delete(std::__1::__function::__default_alloc_func<DB::executeQueryImpl(char const*, char const*, std::__1::shared_ptr<DB::Context>, bool, DB::QueryProcessingStage::Enum, DB::ReadBuffer*)::$_1, void ()>*) @ 0x27706a35 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:15.109645 [ 176653 ] {} <Fatal> BaseDaemon: 20. /build/build_docker/../contrib/libcxx/include/__functional/function.h:633: void std::__1::__function::__policy::__large_destroy<std::__1::__function::__default_alloc_func<DB::executeQueryImpl(char const*, char const*, std::__1::shared_ptr<DB::Context>, bool, DB::QueryProcessingStage::Enum, DB::ReadBuffer*)::$_1, void ()> >(void*) @ 0x27706835 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:15.340956 [ 176653 ] {} <Fatal> BaseDaemon: 21. /build/build_docker/../contrib/libcxx/include/__functional/function.h:0: std::__1::__function::__policy_func<void ()>::operator=(std::nullptr_t) @ 0x17323845 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:15.482268 [ 176653 ] {} <Fatal> BaseDaemon: 22. /build/build_docker/../contrib/libcxx/include/__functional/function.h:820: std::__1::__function::__policy_func<void ()>::operator=(std::__1::__function::__policy_func<void ()>&&) @ 0x17323781 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:15.767446 [ 176653 ] {} <Fatal> BaseDaemon: 23. /build/build_docker/../contrib/libcxx/include/__functional/function.h:1149: std::__1::function<void ()>::operator=(std::__1::function<void ()>&&) @ 0x1731fb6d in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:16.081683 [ 176653 ] {} <Fatal> BaseDaemon: 24. /build/build_docker/../src/QueryPipeline/BlockIO.cpp:38: DB::BlockIO::operator=(DB::BlockIO&&) @ 0x2606923d in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:18.600199 [ 176653 ] {} <Fatal> BaseDaemon: 25. /build/build_docker/../src/Server/TCPHandler.h:47: DB::QueryState::operator=(DB::QueryState&&) @ 0x288449c6 in /usr/bin/clickhouse
/var/log/clickhouse-server/clickhouse-server.err.log:2022.09.10 20:20:42.918741 [ 1473 ] {} <Fatal> Application: Child process was terminated by signal 6.


https://s3.amazonaws.com/clickhouse-test-reports/0/3da8d2e9d4c215572f9eaae7a6735c8266662e1b/stress_test__debug_.html

@FrankChen021
Copy link
Copy Markdown
Contributor Author

@qoega on the master branch? Let me check.

@FrankChen021
Copy link
Copy Markdown
Contributor Author

FrankChen021 commented Sep 12, 2022

Hello @qoega From the log, I can't find the query that lead to the problem. But what I got now is from the stack in the gdb.log

...
2022-09-10 20:18:23 #3  0x00007f7f8a6defd6 in __assert_fail () from /lib/x86_64-linux-gnu/libc.so.6
2022-09-10 20:18:23 #4  0x00000000173f05e4 in DB::OpenTelemetry::SpanHolder::finish (this=0x7f7e05249598) at ../src/Common/OpenTelemetryTraceContext.cpp:127
2022-09-10 20:18:24 #5  0x00000000173f0859 in DB::OpenTelemetry::SpanHolder::~SpanHolder (this=0x7f7e05249598) at ../src/Common/OpenTelemetryTraceContext.cpp:154
2022-09-10 20:18:24 #6  0x0000000027709020 in std::__1::__destroy_at<DB::OpenTelemetry::SpanHolder, 0> (__loc=0x7f7e05249598) at ../contrib/libcxx/include/__memory/construct_at.h:56
2022-09-10 20:18:24 #7  0x0000000027708fb5 in std::__1::destroy_at<DB::OpenTelemetry::SpanHolder, 0> (__loc=0x7f7e05249598) at ../contrib/libcxx/include/__memory/construct_at.h:81
2022-09-10 20:18:24 #8  0x0000000027708f99 in std::__1::allocator_traits<std::__1::allocator<DB::OpenTelemetry::SpanHolder> >::destroy<DB::OpenTelemetry::SpanHolder, void, void> (__p=0x7f7e05249598) at ../contrib/libcxx/include/__memory/allocator_traits.h:317
2022-09-10 20:18:24 #9  0x0000000027708dae in std::__1::__shared_ptr_emplace<DB::OpenTelemetry::SpanHolder, std::__1::allocator<DB::OpenTelemetry::SpanHolder> >::__on_zero_shared (this=0x7f7e05249580) at ../contrib/libcxx/include/__memory/shared_ptr.h:310
2022-09-10 20:18:24         __tmp = {<std::__1::__non_trivial_if<true, std::__1::allocator<DB::OpenTelemetry::SpanHolder> >> = {<No data fields>}, <No data fields>}
2022-09-10 20:18:24 #10 0x00000000172e62d4 in std::__1::__shared_count::__release_shared (this=0x7f7e05249580) at ../contrib/libcxx/include/__memory/shared_ptr.h:174
2022-09-10 20:18:24 #11 0x00000000172e6279 in std::__1::__shared_weak_count::__release_shared (this=0x7f7e05249580) at ../contrib/libcxx/include/__memory/shared_ptr.h:216
2022-09-10 20:18:24 #12 0x000000002770874c in std::__1::shared_ptr<DB::OpenTelemetry::SpanHolder>::~shared_ptr (this=0x7f7ea08b3b88) at ../contrib/libcxx/include/__memory/shared_ptr.h:703
2022-09-10 20:18:24 #13 0x00000000277015c0 in DB::executeQueryImpl(char const*, char const*, std::__1::shared_ptr<DB::Context>, bool, DB::QueryProcessingStage::Enum, DB::ReadBuffer*)::$_1::~$_1() (this=0x7f7ea08b3600) at ../src/Interpreters/executeQuery.cpp:971
2022-09-10 20:18:24 #14 0x0000000027706a95 in std::__1::__function::__default_alloc_func<DB::executeQueryImpl(char const*, char const*, std::__1::shared_ptr<DB::Context>, bool, DB::QueryProcessingStage::Enum, DB::ReadBuffer*)::$_1, void ()>::destroy() (this=0x7f7ea08b3600) at ../contrib/libcxx/include/__functional/function.h:244
2022-09-10 20:18:24 #15 0x0000000027706a35 in std::__1::__function::__default_alloc_func<DB::executeQueryImpl(char const*, char const*, std::__1::shared_ptr<DB::Context>, bool, DB::QueryProcessingStage::Enum, DB::ReadBuffer*)::$_1, void ()>::__destroy_and_delete(std::__1::__function::__default_alloc_func<DB::executeQueryImpl(char const*, char const*, std::__1::shared_ptr<DB::Context>, bool, DB::QueryProcessingStage::Enum, DB::ReadBuffer*)::$_1, void ()>*) (__f=0x7f7ea08b3600) at ../contrib/libcxx/include/__functional/function.h:247
2022-09-10 20:18:24 #16 0x0000000027706835 in std::__1::__function::__policy::__large_destroy<std::__1::__function::__default_alloc_func<DB::executeQueryImpl(char const*, char const*, std::__1::shared_ptr<DB::Context>, bool, DB::QueryProcessingStage::Enum, DB::ReadBuffer*)::$_1, void ()> >(void*) (__s=0x7f7ea08b3600) at ../contrib/libcxx/include/__functional/function.h:632
2022-09-10 20:18:24 No locals.
2022-09-10 20:18:24 #17 0x0000000017323845 in std::__1::__function::__policy_func<void ()>::operator=(decltype(nullptr)) (this=0x7f7e48e355f8) at ../contrib/libcxx/include/__functional/function.h:836
2022-09-10 20:18:24         __p = 0x313d7218 <std::__1::__function::__policy::__choose_policy<std::__1::__function::__default_alloc_func<DB::executeQueryImpl(char const*, char const*, std::__1::shared_ptr<DB::Context>, bool, DB::QueryProcessingStage::Enum, DB::ReadBuffer*)::$_1, void ()> >(std::__1::integral_constant<bool, false>)::__policy_>
2022-09-10 20:18:24 #18 0x0000000017323781 in std::__1::__function::__policy_func<void ()>::operator=(std::__1::__function::__policy_func<void ()>&&) (this=0x7f7e48e355f8, __f=...) at ../contrib/libcxx/include/__functional/function.h:820
2022-09-10 20:18:24 #19 0x000000001731fb6d in std::__1::function<void ()>::operator=(std::__1::function<void ()>&&) (this=0x7f7e48e355f8, __f=...) at ../contrib/libcxx/include/__functional/function.h:1149
2022-09-10 20:18:24 #20 0x000000002606923d in DB::BlockIO::operator= (this=0x7f7e48e354e0, rhs=...) at ../src/QueryPipeline/BlockIO.cpp:38
2022-09-10 20:18:24 #21 0x00000000288449c6 in DB::QueryState::operator= (this=0x7f7e48e35400) at ../src/Server/TCPHandler.h:47
2022-09-10 20:18:24 #22 0x00000000288438ac in DB::QueryState::reset (this=0x7f7e48e35400) at ../src/Server/TCPHandler.h:113
2022-09-10 20:18:24 #23 0x000000002882bd2a in DB::TCPHandler::~TCPHandler (this=0x7f7e48e35200) at ../src/Server/TCPHandler.cpp:116
2022-09-10 20:18:24 #24 0x000000002882c0b9 in DB::TCPHandler::~TCPHandler (this=0x7f7e48e35200) at ../src/Server/TCPHandler.cpp:113
2022-09-10 20:18:24 #25 0x000000002ce9ca34 in std::__1::default_delete<Poco::Net::TCPServerConnection>::operator() (this=0x7f7d1154b670, __ptr=0x7f7e48e35200) at ../contrib/libcxx/include/__memory/unique_ptr.h:54
2022-09-10 20:18:24 #26 0x000000002ce9c99c in std::__1::unique_ptr<Poco::Net::TCPServerConnection, std::__1::default_delete<Poco::Net::TCPServerConnection> >::reset (this=0x7f7d1154b670, __p=0x0) at ../contrib/libcxx/include/__memory/unique_ptr.h:315
2022-09-10 20:18:24         __tmp = 0x7f7e48e35200
2022-09-10 20:18:24 #27 0x000000002ce9c559 in std::__1::unique_ptr<Poco::Net::TCPServerConnection, std::__1::default_delete<Poco::Net::TCPServerConnection> >::~unique_ptr (this=0x7f7d1154b670) at ../contrib/libcxx/include/__memory/unique_ptr.h:269
2022-09-10 20:18:24 #28 0x000000002ce9ba6e in Poco::Net::TCPServerDispatcher::run (this=0x7f7e764d1f00) at ../contrib/poco/Net/src/TCPServerDispatcher.cpp:116

As you can see from the stack level 23, it's from the destructor of TCPHandler.

TCPHandler::~TCPHandler()
{
    try
    {
        state.reset();
        if (out)
            out->next();
    }
    catch (...)
    {
        tryLogCurrentException(__PRETTY_FUNCTION__);
    }
}

The state.reset() call finally result in this problem. From the stack trace, I believe the TCPHandler::runImpl exit from this line(because if there's any exception raised from the runImpl, the try-catch in the while-loop will catch it and then call onException method on the state object to finish the query span first, which won't result in this problem):

if (state.is_connection_closed)
break;

When it exists the while loop, the unique_ptr of TracingContextHolder which is initialized in the while-loop at line

/// Set up tracing context for this query on current thread
thread_trace_context = std::make_unique<OpenTelemetry::TracingContextHolder>("TCPHandler",
query_context->getClientInfo().client_trace_context,
query_context->getSettingsRef(),
query_context->getOpenTelemetrySpanLog());

will be destroyed. Since this holder holds the root span of the tracing context on current thread, its destructor destroys the tracing context kept on thread local.

But the query_span, initialized in executeQuery, which is also referenced by both onFinish and onException callback in BlockIO has not yet been destroyed. It's destroyed in the destructor of TCPHandler. When the span is destroyed, the assert fails because context on current thread is not correct.

In my opinion, when we find that the connection is closed at line 418, we should first reset all necessary resource first before exiting the while-loop, like what line 427 to 429 does.

state.reset();
query_scope.reset();
thread_trace_context.reset();

Since we explicit destroy the resource on state, the query_span implicitly referenced by the object will be cleared before the TracingContextHolder object.

If we don't do that, I have to define TracingContextHolder as a class level object, and put it in the destructor of TCPHandler and destroy it explicitly after state, which makes the TracingContextHolder object and the state tightly coupled.

Correct me if I'm wrong.

@FrankChen021
Copy link
Copy Markdown
Contributor Author

BTW, HTTPHandler does not have such problem, it first creates tracing context and then calls the executeQuery which returns void. This guarantees that the tracing context will be destroyed after any spans.

For GRPCServer, there's no such problem although it calls the same executeQuery as TCPHandler. The GRPCServer split the big while-loop into several steps. And finishQuery or the exception handler will call the same resource clean up method to do the clean up which makes sure the tracing context is destroyed at last.

@FrankChen021
Copy link
Copy Markdown
Contributor Author

I think the problem is clear based on the proof below.

Below is the last line in the log that prints TCP connection is closed by client.

2022.09.10 20:18:23.027550 [ 4723 ] {af089a36-4e0c-49d1-a56b-573b1fd0737c} <Information> TCPHandler: Client has dropped the connection, cancel the query.

From the line above we know that the query id is af089a36-4e0c-49d1-a56b-573b1fd0737c. By search the log of this query, we get:

2022.09.10 20:18:21.747116 [ 4723 ] {af089a36-4e0c-49d1-a56b-573b1fd0737c} <Debug> executeQuery: (from [::1]:52230) (comment: 01003_kill_query_race_condition.sh) SHOW PROCESSLIST (stage: Complete)
2022.09.10 20:18:21.750545 [ 4723 ] {af089a36-4e0c-49d1-a56b-573b1fd0737c} <Debug> executeQuery: (internal) SELECT * FROM system.processes (stage: Complete)
2022.09.10 20:18:21.937055 [ 4723 ] {af089a36-4e0c-49d1-a56b-573b1fd0737c} <Trace> ContextAccess (default): Access granted: SELECT(is_initial_query, user, query_id, address, port, initial_user, initial_query_id, initial_address, initial_port, interface, os_user, client_hostname, client_name, client_revision, client_version_major, client_version_minor, client_version_patch, http_method, http_user_agent, http_referer, forwarded_for, quota_key, distributed_depth, elapsed, is_cancelled, is_all_data_sent, read_rows, read_bytes, total_rows_approx, written_rows, written_bytes, memory_usage, peak_memory_usage, query, thread_ids, ProfileEvents, Settings, current_database) ON system.processes
2022.09.10 20:18:22.469180 [ 4723 ] {af089a36-4e0c-49d1-a56b-573b1fd0737c} <Trace> InterpreterSelectQuery: FetchColumns -> Complete
2022.09.10 20:18:22.880826 [ 4052 ] {af089a36-4e0c-49d1-a56b-573b1fd0737c} <Trace> PipelineExecutor: Thread finished. Total time: 0.01865484 sec. Execution time: 0.004013792 sec. Processing time: 0.012195643 sec. Wait time: 0.002445405 sec.
2022.09.10 20:18:23.027550 [ 4723 ] {af089a36-4e0c-49d1-a56b-573b1fd0737c} <Information> TCPHandler: Client has dropped the connection, cancel the query.
2022.09.10 20:18:23.047525 [ 4723 ] {af089a36-4e0c-49d1-a56b-573b1fd0737c} <Debug> MemoryTracker: Peak memory usage (for query): 3.05 MiB.
2022.09.10 20:18:23.050869 [ 4723 ] {af089a36-4e0c-49d1-a56b-573b1fd0737c} <Debug> TCPHandler: Processed in 1.328887229 sec.

So the query that triggers such problem is SHOW PROCESSLIST. Such query is not inserted into the process list according to line

if (!internal && !ast->as<ASTShowProcesslistQuery>())
{
/// processlist also has query masked now, to avoid secrets leaks though SHOW PROCESSLIST by other users.
process_list_entry = context->getProcessList().insert(query_for_logging, ast.get(), context);
context->setProcessListElement(&process_list_entry->get());
}

And the onFinish callback exit on this condition before it explicit finish the query_span

{
QueryStatus * process_list_elem = context->getProcessListElement();
if (!process_list_elem)
return;

So, the onFinish call at L410 DOES NOT close the SpanHolder which finally leads to this problem.

state.io.onFinish();
/// Do it before sending end of stream, to have a chance to show log message in client.
query_scope->logPeakMemoryUsage();
LOG_DEBUG(log, "Processed in {} sec.", state.watch.elapsedSeconds());
query_duration_already_logged = true;
if (state.is_connection_closed)
break;

I will open a PR to address the problem that the span is not explicitly closed if it's not in process list.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

can be tested Allows running workflows for external contributors pr-improvement Pull request with some product improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants