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 018ac2fdbc4 branch-4.1: [fix](be) Release workload group schedulers on 
shutdown #65112 (#65186)
018ac2fdbc4 is described below

commit 018ac2fdbc484c3f44a6c4f2b871120f5b2be35a
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri Jul 3 20:34:33 2026 +0800

    branch-4.1: [fix](be) Release workload group schedulers on shutdown #65112 
(#65186)
    
    Cherry-picked from #65112
    
    Co-authored-by: TengJianPing <[email protected]>
---
 be/src/exec/pipeline/task_queue.cpp                | 35 +++++++++++++++++-----
 be/src/exec/pipeline/task_queue.h                  |  2 ++
 be/src/exec/scan/scanner_scheduler.h               |  8 +++--
 .../time_sharing/time_sharing_task_executor.cpp    |  7 +++--
 be/src/runtime/exec_env_init.cpp                   |  8 ++++-
 be/src/runtime/workload_group/workload_group.cpp   | 13 ++++++++
 be/src/runtime/workload_group/workload_group.h     |  2 ++
 .../workload_group/workload_group_manager.cpp      |  7 +++++
 .../workload_group/workload_group_manager.h        |  2 ++
 9 files changed, 71 insertions(+), 13 deletions(-)

diff --git a/be/src/exec/pipeline/task_queue.cpp 
b/be/src/exec/pipeline/task_queue.cpp
index db20c7c12fd..126781e59af 100644
--- a/be/src/exec/pipeline/task_queue.cpp
+++ b/be/src/exec/pipeline/task_queue.cpp
@@ -21,6 +21,7 @@
 #include <chrono> // IWYU pragma: keep
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "common/logging.h"
 #include "exec/pipeline/pipeline_task.h"
@@ -38,6 +39,12 @@ PipelineTaskSPtr SubTaskQueue::try_take(bool is_steal) {
     return task;
 }
 
+std::queue<PipelineTaskSPtr> SubTaskQueue::take_all() {
+    std::queue<PipelineTaskSPtr> tasks;
+    tasks.swap(_queue);
+    return tasks;
+}
+
 ////////////////////  PriorityTaskQueue ////////////////////
 
 PriorityTaskQueue::PriorityTaskQueue() : _closed(false) {
@@ -49,10 +56,24 @@ PriorityTaskQueue::PriorityTaskQueue() : _closed(false) {
 }
 
 void PriorityTaskQueue::close() {
-    std::unique_lock<std::mutex> lock(_work_size_mutex);
-    _closed = true;
-    _wait_task.notify_all();
-    
DorisMetrics::instance()->pipeline_task_queue_size->increment(-_total_task_size);
+    std::vector<std::queue<PipelineTaskSPtr>> tasks_to_release;
+    {
+        std::unique_lock<std::mutex> lock(_work_size_mutex);
+        _closed = true;
+        const auto total_task_size = _total_task_size.exchange(0);
+        _wait_task.notify_all();
+        DorisMetrics::instance()->pipeline_task_queue_size->increment(
+                -static_cast<int64_t>(total_task_size));
+        for (auto& sub_queue : _sub_queues) {
+            tasks_to_release.emplace_back(sub_queue.take_all());
+        }
+    }
+    for (auto& tasks : tasks_to_release) {
+        while (!tasks.empty()) {
+            tasks.front()->pop_out_runnable_queue();
+            tasks.pop();
+        }
+    }
 }
 
 PipelineTaskSPtr PriorityTaskQueue::_try_take_unprotected(bool is_steal) {
@@ -114,11 +135,11 @@ PipelineTaskSPtr PriorityTaskQueue::take(uint32_t 
timeout_ms) {
 }
 
 Status PriorityTaskQueue::push(PipelineTaskSPtr task) {
+    auto level = _compute_level(task->get_runtime_ns());
+    std::unique_lock<std::mutex> lock(_work_size_mutex);
     if (_closed) {
         return Status::InternalError("WorkTaskQueue closed");
     }
-    auto level = _compute_level(task->get_runtime_ns());
-    std::unique_lock<std::mutex> lock(_work_size_mutex);
 
     // update empty queue's  runtime, to avoid too high priority
     if (_sub_queues[level].empty() &&
@@ -126,6 +147,7 @@ Status PriorityTaskQueue::push(PipelineTaskSPtr task) {
         _sub_queues[level].adjust_runtime(_queue_level_min_vruntime);
     }
 
+    task->put_in_runnable_queue();
     _sub_queues[level].push_back(task);
     _total_task_size++;
     DorisMetrics::instance()->pipeline_task_queue_size->increment(1);
@@ -200,7 +222,6 @@ Status MultiCoreTaskQueue::push_back(PipelineTaskSPtr task) 
{
 
 Status MultiCoreTaskQueue::push_back(PipelineTaskSPtr task, int core_id) {
     DCHECK(core_id < _core_size);
-    task->put_in_runnable_queue();
     return _prio_task_queues[core_id].push(task);
 }
 
diff --git a/be/src/exec/pipeline/task_queue.h 
b/be/src/exec/pipeline/task_queue.h
index 49796dbcbed..fc4ca1b80bb 100644
--- a/be/src/exec/pipeline/task_queue.h
+++ b/be/src/exec/pipeline/task_queue.h
@@ -57,6 +57,8 @@ public:
 
     bool empty() { return _queue.empty(); }
 
+    std::queue<PipelineTaskSPtr> take_all();
+
 private:
     std::queue<PipelineTaskSPtr> _queue;
     // depends on LEVEL_QUEUE_TIME_FACTOR
diff --git a/be/src/exec/scan/scanner_scheduler.h 
b/be/src/exec/scan/scanner_scheduler.h
index 3635ffc4d11..f1939409bda 100644
--- a/be/src/exec/scan/scanner_scheduler.h
+++ b/be/src/exec/scan/scanner_scheduler.h
@@ -164,7 +164,9 @@ public:
     }
 
     void stop() override {
-        _is_stop.store(true);
+        if (_is_stop.exchange(true)) {
+            return;
+        }
         _scan_thread_pool->shutdown();
         _scan_thread_pool->wait();
     }
@@ -264,7 +266,9 @@ public:
     }
 
     void stop() override {
-        _is_stop.store(true);
+        if (_is_stop.exchange(true)) {
+            return;
+        }
         _task_executor->stop();
         _task_executor->wait();
     }
diff --git 
a/be/src/exec/scan/task_executor/time_sharing/time_sharing_task_executor.cpp 
b/be/src/exec/scan/task_executor/time_sharing/time_sharing_task_executor.cpp
index 138d2df197a..89847de4b29 100644
--- a/be/src/exec/scan/task_executor/time_sharing/time_sharing_task_executor.cpp
+++ b/be/src/exec/scan/task_executor/time_sharing/time_sharing_task_executor.cpp
@@ -274,9 +274,7 @@ Status TimeSharingTaskExecutor::init() {
 }
 
 TimeSharingTaskExecutor::~TimeSharingTaskExecutor() {
-    if (!_stopped.exchange(true)) {
-        stop();
-    }
+    stop();
 
     std::vector<std::shared_ptr<PrioritizedSplitRunner>> splits_to_destroy;
     {
@@ -313,6 +311,9 @@ Status TimeSharingTaskExecutor::start() {
 }
 
 void TimeSharingTaskExecutor::stop() {
+    if (_stopped.exchange(true)) {
+        return;
+    }
     // Why access to doris_metrics is safe here?
     // Since DorisMetrics is a singleton, it will be destroyed only after 
doris_main is exited.
     // The shutdown/destroy of SplitThreadPool is guaranteed to take place 
before doris_main exits by
diff --git a/be/src/runtime/exec_env_init.cpp b/be/src/runtime/exec_env_init.cpp
index d224ac78661..2bce2dc00c5 100644
--- a/be/src/runtime/exec_env_init.cpp
+++ b/be/src/runtime/exec_env_init.cpp
@@ -849,7 +849,8 @@ void ExecEnv::destroy() {
     SAFE_STOP(_stream_load_recorder_manager);
     // stop workload scheduler
     SAFE_STOP(_workload_sched_mgr);
-    // stop pipline step 2, cgroup execution
+    // Stop workload group execution threads before FragmentMgr. Running 
pipeline tasks can still
+    // report status through FragmentMgr's async thread pool.
     SAFE_STOP(_workload_group_manager);
 
     SAFE_STOP(_external_scan_context_mgr);
@@ -862,6 +863,11 @@ void ExecEnv::destroy() {
     _memtable_memory_limiter.reset();
     _delta_writer_v2_pool.reset();
     _load_stream_map_pool.reset();
+    // Workload group schedulers own the query pipeline, scan, and memtable 
flush queues.
+    // Release them after fragment/load resources have stopped submitting 
cleanup work.
+    if (_workload_group_manager) {
+        _workload_group_manager->destroy_schedulers();
+    }
     SAFE_STOP(_write_cooldown_meta_executors);
 
     // _id_manager must be destoried before tablet schema cache
diff --git a/be/src/runtime/workload_group/workload_group.cpp 
b/be/src/runtime/workload_group/workload_group.cpp
index 888f85a7a44..fb70b203f82 100644
--- a/be/src/runtime/workload_group/workload_group.cpp
+++ b/be/src/runtime/workload_group/workload_group.cpp
@@ -745,6 +745,10 @@ int64_t WorkloadGroup::get_mem_used() {
 
 void WorkloadGroup::try_stop_schedulers() {
     std::lock_guard<std::shared_mutex> wlock(_task_sched_lock);
+    stop_schedulers_no_lock();
+}
+
+void WorkloadGroup::stop_schedulers_no_lock() {
     if (_task_sched) {
         _task_sched->stop();
     }
@@ -768,6 +772,15 @@ void WorkloadGroup::try_stop_schedulers() {
     }
 }
 
+void WorkloadGroup::destroy_schedulers() {
+    std::lock_guard<std::shared_mutex> wlock(_task_sched_lock);
+    _task_sched.reset();
+    _scan_task_sched.reset();
+    _remote_scan_task_sched.reset();
+    _memtable_flush_pool.reset();
+    _cgroup_cpu_ctl.reset();
+}
+
 void WorkloadGroup::update_memtable_flush_threads() {
     if (_memtable_flush_pool == nullptr) {
         return;
diff --git a/be/src/runtime/workload_group/workload_group.h 
b/be/src/runtime/workload_group/workload_group.h
index 9b764664adb..2a310bf66a0 100644
--- a/be/src/runtime/workload_group/workload_group.h
+++ b/be/src/runtime/workload_group/workload_group.h
@@ -219,6 +219,8 @@ private:
     void upsert_cgroup_cpu_ctl_no_lock(WorkloadGroupInfo* wg_info);
     Status upsert_thread_pool_no_lock(WorkloadGroupInfo* wg_info,
                                       std::shared_ptr<CgroupCpuCtl> 
cg_cpu_ctl_ptr);
+    void stop_schedulers_no_lock();
+    void destroy_schedulers();
 
     std::string _memory_debug_string() const;
 
diff --git a/be/src/runtime/workload_group/workload_group_manager.cpp 
b/be/src/runtime/workload_group/workload_group_manager.cpp
index 6ea679eb625..019620a586d 100644
--- a/be/src/runtime/workload_group/workload_group_manager.cpp
+++ b/be/src/runtime/workload_group/workload_group_manager.cpp
@@ -944,6 +944,13 @@ void WorkloadGroupMgr::stop() {
     }
 }
 
+void WorkloadGroupMgr::destroy_schedulers() {
+    std::shared_lock<std::shared_mutex> r_lock(_group_mutex);
+    for (auto iter = _workload_groups.begin(); iter != _workload_groups.end(); 
iter++) {
+        iter->second->destroy_schedulers();
+    }
+}
+
 Status WorkloadGroupMgr::create_internal_wg() {
     TWorkloadGroupInfo twg_info;
     twg_info.__set_id(INTERNAL_NORMAL_WG_ID);
diff --git a/be/src/runtime/workload_group/workload_group_manager.h 
b/be/src/runtime/workload_group/workload_group_manager.h
index 4db43b50db1..5b2b1160d60 100644
--- a/be/src/runtime/workload_group/workload_group_manager.h
+++ b/be/src/runtime/workload_group/workload_group_manager.h
@@ -79,6 +79,8 @@ public:
 
     void stop();
 
+    void destroy_schedulers();
+
     void refresh_workload_group_memory_state();
 
     void get_wg_resource_usage(Block* block);


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

Reply via email to