Skip to content

fix(core): resolve FilePool race condition in ensureWatch#29

Merged
CrazyBoyM merged 1 commit intoshareAI-lab:mainfrom
Gui-Yue:fix_fs_tool_bugs
Jan 29, 2026
Merged

fix(core): resolve FilePool race condition in ensureWatch#29
CrazyBoyM merged 1 commit intoshareAI-lab:mainfrom
Gui-Yue:fix_fs_tool_bugs

Conversation

@Gui-Yue
Copy link
Contributor

@Gui-Yue Gui-Yue commented Jan 29, 2026

概述

  • 修复 FilePool.ensureWatch() 中的竞态条件,该问题可能导致重复创建 file watcher
  • 移除 Agent 层冗余的 recordEdit()/recordRead() 调用(工具内部已调用)
  • 添加并发文件操作的回归测试

问题描述

fs_write/fs_edit/fs_multi_edit/fs_read 工具存在双重调用问题:

  1. 工具内部调用 recordEdit()/recordRead()
  2. Agent 层在工具执行后再次调用

这导致 ensureWatch() 中出现竞态条件:
T1: ensureWatch() -> has(path) = false -> await watchFiles()...
T2: ensureWatch() -> has(path) = false -> await watchFiles()... // 竞态!
T3: T1 设置 watchers[path] = id1
T4: T2 设置 watchers[path] = id2 // 覆盖,id1 成为孤儿

后果:

  • 孤儿 watcher 导致资源泄漏
  • 可能耗尽 fs.watch() 系统限制

解决方案

  1. 移除冗余调用 (agent.ts):工具内部已调用 recordEdit()/recordRead(),Agent 层无需重复
  2. 添加 per-path 锁 (file-pool.ts):使用 watchPending Map 防止同一路径并发执行 ensureWatch()

测试验证

  • 原有 226 个单元测试全部通过
  • 新增测试:同一文件并发 recordEdit() 只创建 1 个 watcher
  • 新增测试:不同文件并发 recordEdit() 各自创建独立 watcher
  • 验证无修复时测试失败

  - Remove redundant recordEdit/recordRead calls in agent.ts
    (already called inside fs_read/fs_write/fs_edit/fs_multi_edit tools)
  - Add per-path lock (watchPending Map) to prevent duplicate watchers
    when concurrent calls race through the has() check
  - Add unit tests for concurrent recordEdit scenarios

  Fixes: duplicate watcher creation under concurrent fs operations
@CrazyBoyM CrazyBoyM merged commit 5966520 into shareAI-lab:main Jan 29, 2026
8 checks passed
@CrazyBoyM
Copy link
Contributor

Good Job

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants