fix(dfm-io): close FTS tree in destructor to prevent memory leak#323
Conversation
When initEnumerator(false) is called, openDirByfts() allocates an FTS tree via fts_open(). However, LocalDirIterator::sortFileInfoList() uses its own opendir()/readdir()/closedir() implementation and never calls fts_close(), leaving the FTS tree (5,279 bytes including indirect allocations) leaked. Close the FTS tree in the destructor as a safety net so it is always freed regardless of which sortFileInfoList() code path is taken. Log: Fixed FTS tree memory leak when LocalDirIterator bypasses fts_close(). Assisted-by: deepseek-v4-pro Influence: 1. Open a local directory with dde-file-manager - verify no fts_open leak under Valgrind 2. Test batch directory traversal with sort role set (sortFileInfoList path) 3. Verify one-by-one enumeration path is unaffected 4. Test vault and SMB directory traversal paths 5. Verify rapid open/close of file manager window does not accumulate fts_open leaks fix(dfm-io): 在析构函数中关闭 FTS 树以防止内存泄露 initEnumerator(false) 调用 openDirByfts() 通过 fts_open() 分配 FTS 树,但 LocalDirIterator::sortFileInfoList() 使用自己的 opendir()/readdir()/closedir() 实现,从未调用 fts_close(), 导致 FTS 树(含间接分配共 5,279 字节)泄露。 在析构函数中添加 fts_close() 作为安全兜底,确保无论走哪个 sortFileInfoList() 代码路径,FTS 树都能被释放。 Log: 修复 LocalDirIterator 绕过 fts_close() 导致的 FTS 树内存泄露。 Influence: 1. 使用 dde-file-manager 打开本地目录 — Valgrind 下验证 fts_open 无泄露 2. 测试设置排序角色后的批量目录遍历(sortFileInfoList 路径) 3. 验证逐个遍历路径不受影响 4. 测试保险箱和 SMB 目录遍历路径 5. 验证快速打开/关闭文件管理器窗口不累积 fts_open 泄露
Reviewer's guide (collapsed on small PRs)Reviewer's GuideEnsures the FTS directory traversal tree allocated by initEnumerator(false)/openDirByfts() is always closed by adding an fts_close() safety net in the DEnumeratorPrivate destructor, preventing a memory leak when certain sortFileInfoList() code paths bypass fts_close(). Sequence diagram for FTS tree lifecycle with destructor safety netsequenceDiagram
participant DEnumeratorPrivate
participant openDirByfts
participant FTS_library
DEnumeratorPrivate->>openDirByfts: initEnumerator(false)
openDirByfts->>FTS_library: fts_open
FTS_library-->>openDirByfts: fts_handle
openDirByfts-->>DEnumeratorPrivate: store fts_handle
rect rgb(230,230,230)
DEnumeratorPrivate-->>DEnumeratorPrivate: [sortFileInfoList path bypasses fts_close]
end
DEnumeratorPrivate->>FTS_library: ~DEnumeratorPrivate
DEnumeratorPrivate->>FTS_library: fts_close
FTS_library-->>DEnumeratorPrivate: fts_tree_freed
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- Since the destructor now unconditionally closes
ftswhen non-null, please verify any other code paths that callfts_closealso setftstonullptrto avoid a potential double-close if future changes alter ownership assumptions. - Consider wrapping the raw
ftspointer in a small RAII helper (or a dedicated member type) so that lifetime and ownership are expressed more clearly and future changes cannot forget to close it.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Since the destructor now unconditionally closes `fts` when non-null, please verify any other code paths that call `fts_close` also set `fts` to `nullptr` to avoid a potential double-close if future changes alter ownership assumptions.
- Consider wrapping the raw `fts` pointer in a small RAII helper (or a dedicated member type) so that lifetime and ownership are expressed more clearly and future changes cannot forget to close it.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
deepin pr auto review★ 总体评分:100分■ 【总体评价】
■ 【详细分析】
■ 【改进建议代码示例】 DEnumeratorPrivate::~DEnumeratorPrivate()
{
if (cancellable) {
g_object_unref(cancellable);
cancellable = nullptr;
}
if (fts) {
fts_close(fts);
fts = nullptr;
}
} |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: Johnson-zs, liujianqiang-niu, liyigang1 The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
When initEnumerator(false) is called, openDirByfts() allocates an FTS tree via fts_open(). However, LocalDirIterator::sortFileInfoList() uses its own opendir()/readdir()/closedir() implementation and never calls fts_close(), leaving the FTS tree (5,279 bytes including indirect allocations) leaked.
Close the FTS tree in the destructor as a safety net so it is always freed regardless of which sortFileInfoList() code path is taken.
Log: Fixed FTS tree memory leak when LocalDirIterator bypasses fts_close().
Assisted-by: deepseek-v4-pro
Influence:
fix(dfm-io): 在析构函数中关闭 FTS 树以防止内存泄露
initEnumerator(false) 调用 openDirByfts() 通过 fts_open() 分配 FTS 树,但 LocalDirIterator::sortFileInfoList() 使用自己的 opendir()/readdir()/closedir() 实现,从未调用 fts_close(), 导致 FTS 树(含间接分配共 5,279 字节)泄露。
在析构函数中添加 fts_close() 作为安全兜底,确保无论走哪个
sortFileInfoList() 代码路径,FTS 树都能被释放。
Log: 修复 LocalDirIterator 绕过 fts_close() 导致的 FTS 树内存泄露。
Influence:
Summary by Sourcery
Bug Fixes: