This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.1 by this push:
new b85792bb113 branch-4.1: [fix](be) Initialize bthread context key
before first use (#67722)
b85792bb113 is described below
commit b85792bb113a4b521f82329ab3ad29d5886c4ba1
Author: hui lai <[email protected]>
AuthorDate: Thu Sep 10 09:29:07 2026 +0800
branch-4.1: [fix](be) Initialize bthread context key before first use
(#67722)
### What problem does this PR solve?
Backport #67580 to branch-4.1.
A bthread could create its ThreadContext before its key was initialized.
Later key creation changed the key version, causing context lookup to
return null and scoped memory-tracker cleanup to crash. Initialize the
key once before first use and retain it for the process lifetime.
The conflict in thread_context.cpp was resolved by retaining the
branch-4.1 function layout. The added and removed lines match the
original PR.
### Release note
Fix a potential BE crash during scoped memory-tracker cleanup caused by
bthread context key initialization.
### Check List (For Author)
- Test: Compilation and tests skipped as requested. clang-format 16 and
git diff --check passed.
- Behavior changed: Yes; initialize the bthread context key before first
use and preserve its process lifetime.
- Does this need documentation: No.
---
be/src/runtime/thread_context.cpp | 18 ++++++++++++++++++
be/src/runtime/thread_context.h | 5 +++++
be/src/service/internal_service.cpp | 8 --------
3 files changed, 23 insertions(+), 8 deletions(-)
diff --git a/be/src/runtime/thread_context.cpp
b/be/src/runtime/thread_context.cpp
index 83f38369d6c..9443625ab3e 100644
--- a/be/src/runtime/thread_context.cpp
+++ b/be/src/runtime/thread_context.cpp
@@ -17,6 +17,8 @@
#include "runtime/thread_context.h"
+#include <mutex>
+
#include "common/signal_handler.h"
#include "runtime/query_context.h"
#include "runtime/runtime_state.h"
@@ -24,6 +26,22 @@
namespace doris {
class MemTracker;
+bthread_key_t btls_key;
+
+namespace {
+
+void thread_context_deleter(void* data) {
+ delete static_cast<ThreadContext*>(data);
+}
+
+} // namespace
+
+void init_thread_context_btls_key() {
+ static std::once_flag btls_key_once;
+ std::call_once(btls_key_once,
+ []() { CHECK_EQ(0, bthread_key_create(&btls_key,
thread_context_deleter)); });
+}
+
void AttachTask::init(const std::shared_ptr<ResourceContext>& rc) {
// Validate the ResourceContext chain before mutating any thread-local
// or signal state. If any link is null we throw immediately, so the
diff --git a/be/src/runtime/thread_context.h b/be/src/runtime/thread_context.h
index 332cd0f6545..c0168daceb2 100644
--- a/be/src/runtime/thread_context.h
+++ b/be/src/runtime/thread_context.h
@@ -140,6 +140,10 @@ class SwitchResourceContext;
extern bthread_key_t btls_key;
+// Initialize btls_key exactly once before it is used by any thread context.
The key has
+// process lifetime so an existing bthread context never becomes invalid while
the BE is running.
+void init_thread_context_btls_key();
+
static std::string NO_THREAD_CONTEXT_MSG =
"Current thread not exist ThreadContext, usually after the thread is
started, using "
"SCOPED_ATTACH_TASK macro to create a ThreadContext and bind a Task.";
@@ -224,6 +228,7 @@ private:
class ThreadLocalHandle {
public:
static void create_thread_local_if_not_exits() {
+ init_thread_context_btls_key();
if (bthread_self() == 0) {
if (!pthread_context_ptr_init) {
thread_context_ptr = new ThreadContext();
diff --git a/be/src/service/internal_service.cpp
b/be/src/service/internal_service.cpp
index 673001aa987..96142dae0b6 100644
--- a/be/src/service/internal_service.cpp
+++ b/be/src/service/internal_service.cpp
@@ -167,12 +167,6 @@
DEFINE_GAUGE_METRIC_PROTOTYPE_2ARG(arrow_flight_work_max_threads, MetricUnit::NO
static bvar::LatencyRecorder
g_process_remote_fetch_rowsets_latency("process_remote_fetch_rowsets");
-bthread_key_t btls_key;
-
-static void thread_context_deleter(void* d) {
- delete static_cast<ThreadContext*>(d);
-}
-
static int32_t resolved_brpc_peer_fetch_pool_threads() {
return config::brpc_peer_fetch_pool_threads != -1 ?
config::brpc_peer_fetch_pool_threads
: std::max(64,
CpuInfo::num_cores() * 2);
@@ -293,7 +287,6 @@ PInternalService::PInternalService(ExecEnv* exec_env)
_exec_env->load_stream_mgr()->set_heavy_work_pool(&_heavy_work_pool);
- CHECK_EQ(0, bthread_key_create(&btls_key, thread_context_deleter));
CHECK_EQ(0, bthread_key_create(&AsyncIO::btls_io_ctx_key,
AsyncIO::io_ctx_key_deleter));
}
@@ -322,7 +315,6 @@ PInternalService::~PInternalService() {
DEREGISTER_HOOK_METRIC(arrow_flight_work_pool_max_queue_size);
DEREGISTER_HOOK_METRIC(arrow_flight_work_max_threads);
- CHECK_EQ(0, bthread_key_delete(btls_key));
CHECK_EQ(0, bthread_key_delete(AsyncIO::btls_io_ctx_key));
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]