This is an automated email from the ASF dual-hosted git repository.

gavinchou pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 310e302bcc9 [fix](be) Stop background workers before startup exit 
(#68652)
310e302bcc9 is described below

commit 310e302bcc975b91265ac589a264d80fb25160e5
Author: Gavin Chou <[email protected]>
AuthorDate: Thu Oct 8 12:22:42 2026 +0800

    [fix](be) Stop background workers before startup exit (#68652)
    
    When a BE service fails to start with `enable_graceful_exit_check=true`,
    the startup failure path calls `exit(1)` while StorageEngine background
    workers are still running. `exit(1)` begins process-wide static
    destruction before `ExecEnv` and `StorageEngine` are torn down.
    
    A path GC worker can therefore keep matching tablet paths while the
    function-local static RE2 object in
    `TabletManager::get_tablet_id_and_schema_hash_from_path()` is being
    destroyed. This was observed after the backend Thrift port failed to
    bind: the path GC thread crashed at address `0x0` in
    `re2::Prog::SearchOnePass`, and the main thread subsequently waited
    indefinitely for that worker.
    
    This change:
    
    - stops and joins every created server starter on the graceful
    startup-failure path;
    - releases the backend service before destroying its dependencies;
    - explicitly destroys `ExecEnv`, which stops and joins StorageEngine
    workers, before calling `exit(1)`;
    - preserves the existing immediate `_exit(1)` behavior when graceful
    exit checking is disabled.
    
    Failed starters are joined to release partially initialized resources,
    while `stop()` is called only for starters that completed startup
    successfully.
---
 be/src/service/doris_main.cpp | 69 +++++++++++++++++++++++++++++++++----------
 1 file changed, 54 insertions(+), 15 deletions(-)

diff --git a/be/src/service/doris_main.cpp b/be/src/service/doris_main.cpp
index fd7f0746e3d..374d698a2a5 100644
--- a/be/src/service/doris_main.cpp
+++ b/be/src/service/doris_main.cpp
@@ -353,10 +353,18 @@ struct Checker {
 // running the leak check on this abnormal-exit path reports them as 
false-positive
 // leaks. enable_graceful_exit_check is honored so memleak-check mode still 
runs LSAN.
 [[noreturn]] static void exit_on_startup_failure() {
-    google::FlushLogFiles(google::GLOG_INFO);
     if (!doris::config::enable_graceful_exit_check) {
+        google::FlushLogFiles(google::GLOG_INFO);
         _exit(1);
     }
+
+    // exit() starts destroying function-local statics while background 
threads are still
+    // running. Tear down ExecEnv first so StorageEngine workers are stopped 
and joined before
+    // they can race with those destructors.
+    if (doris::ExecEnv::ready()) {
+        doris::ExecEnv::GetInstance()->destroy();
+    }
+    google::FlushLogFiles(google::GLOG_INFO);
     exit(1);
 }
 
@@ -662,11 +670,38 @@ int main(int argc, char** argv) {
     doris::ThriftRpcHelper::setup(exec_env);
     // 1. thrift server with be_port
     std::shared_ptr<doris::BaseBackendService> service;
+    std::unique_ptr<doris::server::IServerStarter> backend_thrift_starter;
+    std::unique_ptr<doris::server::IServerStarter> brpc_starter;
+    std::unique_ptr<doris::server::IServerStarter> http_starter;
+    std::unique_ptr<doris::server::IServerStarter> heartbeat_thrift_starter;
+    std::unique_ptr<doris::server::IServerStarter> flight_starter;
+    bool backend_thrift_started = false;
+    bool brpc_started = false;
+    bool http_started = false;
+    bool heartbeat_thrift_started = false;
+    bool flight_started = false;
+    auto stop_and_join_server = 
[](std::unique_ptr<doris::server::IServerStarter>& starter,
+                                   bool started) {
+        if (starter != nullptr) {
+            if (started) {
+                starter->stop();
+            }
+            starter->join();
+        }
+    };
     std::function<void(Status&, std::string_view)> stop_work_if_error = 
[&](Status& status,
                                                                             
std::string_view msg) {
         if (!status.ok()) {
             std::cerr << msg << '\n';
             service->stop_works();
+            if (doris::config::enable_graceful_exit_check) {
+                stop_and_join_server(flight_starter, flight_started);
+                stop_and_join_server(heartbeat_thrift_starter, 
heartbeat_thrift_started);
+                stop_and_join_server(http_starter, http_started);
+                stop_and_join_server(backend_thrift_starter, 
backend_thrift_started);
+                stop_and_join_server(brpc_starter, brpc_started);
+                service.reset();
+            }
             exit_on_startup_failure();
         }
     };
@@ -679,44 +714,48 @@ int main(int argc, char** argv) {
                                                           exec_env);
     }
 
-    std::unique_ptr<doris::server::IServerStarter> backend_thrift_starter;
-    EXIT_IF_ERROR(doris::server::create_backend_thrift_starter(exec_env, 
doris::config::be_port,
-                                                               service, 
&backend_thrift_starter));
+    status = doris::server::create_backend_thrift_starter(exec_env, 
doris::config::be_port, service,
+                                                          
&backend_thrift_starter);
+    stop_work_if_error(status, "Failed to create BE server, exiting");
     status = backend_thrift_starter->start();
+    backend_thrift_started = status.ok();
     stop_work_if_error(status, "Doris BE server did not start correctly, 
exiting");
 
     // 2. brpc service
-    std::unique_ptr<doris::server::IServerStarter> brpc_starter;
-    EXIT_IF_ERROR(doris::server::create_brpc_starter(
-            exec_env, doris::config::brpc_port, 
doris::config::brpc_num_threads, &brpc_starter));
+    status = doris::server::create_brpc_starter(exec_env, 
doris::config::brpc_port,
+                                                
doris::config::brpc_num_threads, &brpc_starter);
+    stop_work_if_error(status, "Failed to create BRPC service, exiting");
     status = brpc_starter->start();
+    brpc_started = status.ok();
     stop_work_if_error(status, "BRPC service did not start correctly, 
exiting");
 
     // 3. http service
-    std::unique_ptr<doris::server::IServerStarter> http_starter;
-    EXIT_IF_ERROR(doris::server::create_http_starter(exec_env, 
doris::config::webserver_port,
-                                                     
doris::config::webserver_num_workers,
-                                                     &http_starter));
+    status =
+            doris::server::create_http_starter(exec_env, 
doris::config::webserver_port,
+                                               
doris::config::webserver_num_workers, &http_starter);
+    stop_work_if_error(status, "Failed to create BE HTTP service, exiting");
     status = http_starter->start();
+    http_started = status.ok();
     stop_work_if_error(status, "Doris Be http service did not start correctly, 
exiting");
 
     // 4. heart beat server
     doris::ClusterInfo* cluster_info = exec_env->cluster_info();
-    std::unique_ptr<doris::server::IServerStarter> heartbeat_thrift_starter;
     status = doris::server::create_heartbeat_thrift_starter(
             exec_env, doris::config::heartbeat_service_port,
             doris::config::heartbeat_service_thread_count, cluster_info, 
&heartbeat_thrift_starter);
     stop_work_if_error(status, "Heartbeat services did not start correctly, 
exiting");
 
     status = heartbeat_thrift_starter->start();
+    heartbeat_thrift_started = status.ok();
     stop_work_if_error(status, "Doris BE HeartBeat Service did not start 
correctly, exiting: " +
                                        status.to_string());
 
     // 5. arrow flight service
-    std::unique_ptr<doris::server::IServerStarter> flight_starter;
-    
EXIT_IF_ERROR(doris::server::create_flight_starter(doris::config::arrow_flight_sql_port,
-                                                       &flight_starter));
+    status = 
doris::server::create_flight_starter(doris::config::arrow_flight_sql_port,
+                                                  &flight_starter);
+    stop_work_if_error(status, "Failed to create Arrow Flight service, 
exiting");
     status = flight_starter->start();
+    flight_started = status.ok();
     stop_work_if_error(
             status, "Arrow Flight Service did not start correctly, exiting, " 
+ status.to_string());
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to