Skip to content

Commit ee6d26d

Browse files
committed
fix: add ScopeGuard to wait async tasks before early return in Clean()
When GetUsedFiles() returns an error (e.g. index manifest not supported), Clean() would return immediately while thread pool tasks submitted via Via(executor_.get(), ...) were still running. These tasks capture 'this' and access members like fs_, causing use-after-free when the OrphanFilesCleanerImpl is destroyed shortly after. Add a ScopeGuard that calls CollectAll(file_statuses_futures) to ensure all submitted async tasks complete before the function returns, preventing the intermittent segmentation fault.
1 parent 2d5fdbf commit ee6d26d

2 files changed

Lines changed: 5 additions & 1 deletion

File tree

src/paimon/common/executor/future.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,9 @@ std::vector<T> CollectAll(std::vector<std::future<T>>& futures) {
9696
std::vector<T> results;
9797
results.reserve(futures.size()); // Reserve space to avoid reallocation.
9898
for (auto& future : futures) {
99-
results.push_back(future.get()); // Wait for each future and collect the result.
99+
if (future.valid()) {
100+
results.push_back(future.get());
101+
}
100102
}
101103

102104
return results;

src/paimon/core/operation/orphan_files_cleaner_impl.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ Result<std::set<std::string>> OrphanFilesCleanerImpl::Clean() {
9797
}
9898
PAIMON_ASSIGN_OR_RAISE(std::set<std::string> all_dirs, ListPaimonFileDirs());
9999
std::vector<std::future<std::vector<std::unique_ptr<FileStatus>>>> file_statuses_futures;
100+
ScopeGuard file_statuses_guard(
101+
[&file_statuses_futures]() { CollectAll(file_statuses_futures); });
100102
for (const auto& dir : all_dirs) {
101103
file_statuses_futures.push_back(
102104
Via(executor_.get(), [this, dir] { return TryBestListingDirs(dir); }));

0 commit comments

Comments
 (0)