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

zouxinyi 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 d1dbe7bfc8 [fix](reader) fix leak in Level1Iteartor (#23612)
d1dbe7bfc8 is described below

commit d1dbe7bfc840eca5c497a1aee793493370bbde9b
Author: walter <w41te...@gmail.com>
AuthorDate: Tue Aug 29 23:32:24 2023 +0800

    [fix](reader) fix leak in Level1Iteartor (#23612)
    
    _merge_next() and _normal_next() leak _cur_child when _cur_child->next()
    returns failure.
---
 be/src/vec/olap/vcollect_iterator.cpp | 100 ++++++++++++++--------------------
 be/src/vec/olap/vcollect_iterator.h   |  12 ++--
 2 files changed, 47 insertions(+), 65 deletions(-)

diff --git a/be/src/vec/olap/vcollect_iterator.cpp 
b/be/src/vec/olap/vcollect_iterator.cpp
index 78fad44fb7..a85f526d65 100644
--- a/be/src/vec/olap/vcollect_iterator.cpp
+++ b/be/src/vec/olap/vcollect_iterator.cpp
@@ -58,11 +58,7 @@ namespace vectorized {
         }                                                              \
     } while (false)
 
-VCollectIterator::~VCollectIterator() {
-    for (auto child : _children) {
-        delete child;
-    }
-}
+VCollectIterator::~VCollectIterator() = default;
 
 void VCollectIterator::init(TabletReader* reader, bool ori_data_overlapping, 
bool force_merge,
                             bool is_reverse) {
@@ -102,8 +98,7 @@ Status VCollectIterator::add_child(const RowSetSplits& 
rs_splits) {
         return Status::OK();
     }
 
-    std::unique_ptr<LevelIterator> child(new 
Level0Iterator(rs_splits.rs_reader, _reader));
-    _children.push_back(child.release());
+    _children.push_back(std::make_unique<Level0Iterator>(rs_splits.rs_reader, 
_reader));
     return Status::OK();
 }
 
@@ -127,7 +122,6 @@ Status 
VCollectIterator::build_heap(std::vector<RowsetReaderSharedPtr>& rs_reade
              c_iter != _children.end();) {
             auto s = (*c_iter)->init(have_multiple_child);
             if (!s.ok()) {
-                delete (*c_iter);
                 c_iter = _children.erase(c_iter);
                 r_iter = rs_readers.erase(r_iter);
                 if (!s.is<END_OF_FILE>()) {
@@ -156,39 +150,38 @@ Status 
VCollectIterator::build_heap(std::vector<RowsetReaderSharedPtr>& rs_reade
             auto base_reader_child = _children.begin();
             std::advance(base_reader_child, base_reader_idx);
 
-            std::list<LevelIterator*> cumu_children;
+            std::list<std::unique_ptr<LevelIterator>> cumu_children;
             for (auto iter = _children.begin(); iter != _children.end();) {
                 if (iter != base_reader_child) {
-                    cumu_children.push_back(*iter);
+                    cumu_children.push_back(std::move(*iter));
                     iter = _children.erase(iter);
                 } else {
                     ++iter;
                 }
             }
-            auto cumu_iter = std::make_unique<Level1Iterator>(
-                    cumu_children, _reader, cumu_children.size() > 1, 
_is_reverse, _skip_same);
+            bool is_merge = cumu_children.size() > 1;
+            std::unique_ptr<LevelIterator> cumu_iter = 
std::make_unique<Level1Iterator>(
+                    std::move(cumu_children), _reader, is_merge, _is_reverse, 
_skip_same);
             RETURN_IF_NOT_EOF_AND_OK(cumu_iter->init());
-            std::list<LevelIterator*> children;
-            children.push_back(*base_reader_child);
-            children.push_back(cumu_iter.get());
-            auto level1_iter =
-                    new Level1Iterator(children, _reader, _merge, _is_reverse, 
_skip_same);
-            cumu_iter.release();
-            _inner_iter.reset(level1_iter);
+            std::list<std::unique_ptr<LevelIterator>> children;
+            children.push_back(std::move(*base_reader_child));
+            children.push_back(std::move(cumu_iter));
+            _inner_iter.reset(new Level1Iterator(std::move(children), _reader, 
_merge, _is_reverse,
+                                                 _skip_same));
             // need to clear _children here, or else if the following 
_inner_iter->init() return early
             // base_reader_child will be double deleted
             _children.clear();
         } else {
             // _children.size() == 1
-            _inner_iter.reset(
-                    new Level1Iterator(_children, _reader, _merge, 
_is_reverse, _skip_same));
+            _inner_iter.reset(new Level1Iterator(std::move(_children), 
_reader, _merge, _is_reverse,
+                                                 _skip_same));
         }
     } else {
-        auto level1_iter = std::make_unique<Level1Iterator>(_children, 
_reader, _merge, _is_reverse,
-                                                            _skip_same);
+        auto level1_iter = 
std::make_unique<Level1Iterator>(std::move(_children), _reader, _merge,
+                                                            _is_reverse, 
_skip_same);
         _children.clear();
         RETURN_IF_ERROR(level1_iter->init_level0_iterators_for_union());
-        _inner_iter.reset(level1_iter.release());
+        _inner_iter = std::move(level1_iter);
     }
     RETURN_IF_NOT_EOF_AND_OK(_inner_iter->init());
     // Clear _children earlier to release any related references
@@ -592,10 +585,10 @@ Status 
VCollectIterator::Level0Iterator::current_block_row_locations(
 }
 
 VCollectIterator::Level1Iterator::Level1Iterator(
-        const std::list<VCollectIterator::LevelIterator*>& children, 
TabletReader* reader,
+        std::list<std::unique_ptr<VCollectIterator::LevelIterator>> children, 
TabletReader* reader,
         bool merge, bool is_reverse, bool skip_same)
         : LevelIterator(reader),
-          _children(children),
+          _children(std::move(children)),
           _reader(reader),
           _merge(merge),
           _is_reverse(is_reverse),
@@ -608,20 +601,10 @@ VCollectIterator::Level1Iterator::Level1Iterator(
 }
 
 VCollectIterator::Level1Iterator::~Level1Iterator() {
-    for (auto child : _children) {
-        if (child != nullptr) {
-            delete child;
-            child = nullptr;
-        }
-    }
-
     if (_heap) {
         while (!_heap->empty()) {
-            auto child = _heap->top();
+            delete _heap->top();
             _heap->pop();
-            if (child) {
-                delete child;
-            }
         }
     }
 }
@@ -681,18 +664,20 @@ Status VCollectIterator::Level1Iterator::init(bool 
get_data_by_ref) {
             }
         }
         _heap.reset(new MergeHeap {LevelIteratorComparator(sequence_loc, 
_is_reverse)});
-        for (auto child : _children) {
+        for (auto&& child : _children) {
             DCHECK(child != nullptr);
             //DCHECK(child->current_row().ok());
-            _heap->push(child);
+            _heap->push(child.release());
         }
-        _cur_child = _heap->top();
+        _cur_child.reset(_heap->top());
+        _heap->pop();
         // Clear _children earlier to release any related references
         _children.clear();
     } else {
         _merge = false;
         _heap.reset(nullptr);
-        _cur_child = *_children.begin();
+        _cur_child = std::move(*_children.begin());
+        _children.pop_front();
     }
     _ref = *_cur_child->current_row_ref();
     return Status::OK();
@@ -704,7 +689,6 @@ Status 
VCollectIterator::Level1Iterator::init_level0_iterators_for_union() {
     for (auto iter = _children.begin(); iter != _children.end();) {
         auto s = (*iter)->init_for_union(is_first_child, have_multiple_child);
         if (!s.ok()) {
-            delete (*iter);
             iter = _children.erase(iter);
             if (!s.is<END_OF_FILE>()) {
                 return s;
@@ -720,24 +704,24 @@ Status 
VCollectIterator::Level1Iterator::init_level0_iterators_for_union() {
 }
 
 Status VCollectIterator::Level1Iterator::_merge_next(IteratorRowRef* ref) {
-    _heap->pop();
     auto res = _cur_child->next(ref);
     if (LIKELY(res.ok())) {
-        _heap->push(_cur_child);
-        _cur_child = _heap->top();
+        _heap->push(_cur_child.release());
+        _cur_child.reset(_heap->top());
+        _heap->pop();
     } else if (res.is<END_OF_FILE>()) {
         // current child has been read, to read next
-        delete _cur_child;
         if (!_heap->empty()) {
-            _cur_child = _heap->top();
+            _cur_child.reset(_heap->top());
+            _heap->pop();
         } else {
             _ref.reset();
-            _cur_child = nullptr;
+            _cur_child.reset();
             return Status::Error<END_OF_FILE>("");
         }
     } else {
         _ref.reset();
-        _cur_child = nullptr;
+        _cur_child.reset();
         LOG(WARNING) << "failed to get next from child, res=" << res;
         return res;
     }
@@ -763,17 +747,16 @@ Status 
VCollectIterator::Level1Iterator::_normal_next(IteratorRowRef* ref) {
         return Status::OK();
     } else if (res.is<END_OF_FILE>()) {
         // current child has been read, to read next
-        delete _cur_child;
-        _children.pop_front();
         if (!_children.empty()) {
-            _cur_child = *(_children.begin());
+            _cur_child = std::move(*(_children.begin()));
+            _children.pop_front();
             return _normal_next(ref);
         } else {
-            _cur_child = nullptr;
+            _cur_child.reset();
             return Status::Error<END_OF_FILE>("");
         }
     } else {
-        _cur_child = nullptr;
+        _cur_child.reset();
         LOG(WARNING) << "failed to get next from child, res=" << res;
         return res;
     }
@@ -861,17 +844,16 @@ Status 
VCollectIterator::Level1Iterator::_normal_next(Block* block) {
         return Status::OK();
     } else if (res.is<END_OF_FILE>()) {
         // current child has been read, to read next
-        delete _cur_child;
-        _children.pop_front();
         if (!_children.empty()) {
-            _cur_child = *(_children.begin());
+            _cur_child = std::move(*(_children.begin()));
+            _children.pop_front();
             return _normal_next(block);
         } else {
-            _cur_child = nullptr;
+            _cur_child.reset();
             return Status::Error<END_OF_FILE>("");
         }
     } else {
-        _cur_child = nullptr;
+        _cur_child.reset();
         LOG(WARNING) << "failed to get next from child, res=" << res;
         return res;
     }
diff --git a/be/src/vec/olap/vcollect_iterator.h 
b/be/src/vec/olap/vcollect_iterator.h
index 7faa47ac2b..3fa9849289 100644
--- a/be/src/vec/olap/vcollect_iterator.h
+++ b/be/src/vec/olap/vcollect_iterator.h
@@ -258,8 +258,8 @@ private:
     // Iterate from LevelIterators (maybe Level0Iterators or Level1Iterator or 
mixed)
     class Level1Iterator : public LevelIterator {
     public:
-        Level1Iterator(const std::list<LevelIterator*>& children, 
TabletReader* reader, bool merge,
-                       bool is_reverse, bool skip_same);
+        Level1Iterator(std::list<std::unique_ptr<LevelIterator>> children, 
TabletReader* reader,
+                       bool merge, bool is_reverse, bool skip_same);
 
         Status init(bool get_data_by_ref = false) override;
 
@@ -295,10 +295,10 @@ private:
 
         // Each LevelIterator corresponds to a rowset reader,
         // it will be cleared after '_heap' has been initialized when '_merge 
== true'.
-        std::list<LevelIterator*> _children;
+        std::list<std::unique_ptr<LevelIterator>> _children;
         // point to the Level0Iterator containing the next output row.
         // null when VCollectIterator hasn't been initialized or reaches EOF.
-        LevelIterator* _cur_child = nullptr;
+        std::unique_ptr<LevelIterator> _cur_child;
         TabletReader* _reader = nullptr;
 
         // when `_merge == true`, rowset reader returns ordered rows and 
VCollectIterator uses a priority queue to merge
@@ -321,7 +321,7 @@ private:
 
     // Each LevelIterator corresponds to a rowset reader,
     // it will be cleared after '_inner_iter' has been initialized.
-    std::list<LevelIterator*> _children;
+    std::list<std::unique_ptr<LevelIterator>> _children;
 
     bool _merge = true;
     // reverse the compare order
@@ -338,4 +338,4 @@ private:
 };
 
 } // namespace vectorized
-} // namespace doris
\ No newline at end of file
+} // namespace doris


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to