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]

Reply via email to