Skip to content

[Bug]: Glob/Grep 工具偶发长时间挂起(可达数分钟),Flashgrep RPC 调用链无超时 #2305

Description

@Raing5Days

Summary

Glob 与 Grep 工具在本地 workspace 上偶发长时间无结果(实测约 5 分钟,直到宿主侧取消;同一调用重放可再次失败)。文件系统扫描本身不是瓶颈(src/ 全树 5713 个文件递归扫描实测约 411ms),根因是这两个工具在本地路径优先路由到 Flashgrep 索引服务,而整条 RPC 调用链没有超时保护:当 flashgrep daemon 进程存活但不响应请求(索引重建、内部卡死)时,客户端无限等待,直到 daemon 退出或宿主取消。

  • 类型: Bug / 可靠性
  • 严重度: 高(工具挂起 5 分钟级,阻塞 agent 工作流)
  • 影响面: 桌面端 Glob/Grep 工具(本地 workspace),所有开启 workspace-search 的用户

Area

Desktop app

Reproduction or evidence

复现步骤:

  1. 开启 app.ai_experience.enable_workspace_search(默认路径即走 Flashgrep)。
  2. 确认 flashgrep daemon 二进制存在且进程存活(本机 FLASHGREP_DAEMON_BIN 已设置,daemon PID 6020 在运行)。
  3. 使 daemon 处于忙/不健康状态(例如存在待处理脏文件、索引重建中或内部卡死但进程未退出)。
  4. 调用 Glob(如 Glob pattern="src/crates/assembly/core/src/agentic/tools/implementations/task*",该目录确实存在)或 Grep。
  5. 观察工具长时间无返回;daemon 健康时秒回,不健康时挂起,表现为不定时偶发。

复现率: 非确定性,取决于 daemon 健康状态。两次独立失败(用户环境一次 + 原样重放一次)。

代码证据(调用链无超时)

位置 事实
glob_tool.rs:419-426 search_service.glob(...).await 无 timeout;同文件 remote shell 分支有 Some(30_000) / Some(5_000) 超时(L339、L364)
grep_tool.rs:691 search_service.search_content(request).await? 无 timeout;remote 分支有 Some(30_000)(L159)
flashgrep/client.rs:264、310 RepoSession::search/glob 均以 None 超时调用 RPC(仅 close 有 2s 超时,L372)
flashgrep/rpc_client.rs:92-114 request_timeout=Nonereceiver.await 无限等待,仅 daemon 关 stdout/退出才解除;daemon 存活但不回包时 pending 请求永不 resolve
service/search/service.rs:189-191 workspace_search_runtime_available() 只检查 feature flag + 二进制存在,不探活 daemon;daemon 已卡死时仍走 Flashgrep 路径,不降级到本地 rg

根因调用链(本地路径)

GlobTool/GrepTool
  → workspace_search_runtime_available()  // 仅查 feature flag + 二进制存在,不探活
  → WorkspaceSearchService::glob/search_content   // 无 timeout(service.rs)
  → RepoSession::glob/search/status       // timeout = None(client.rs:264,310)
  → ProtocolClient::send_request_with_timeout(None)  // receiver.await 无限等待(rpc_client.rs:108)

关键缺陷:

  1. RPC 层无超时RepoSessionsearch/glob/status/task_status 均以 None 超时调用(仅 close 有 2s)。ProtocolClientrequest_timeout=None 时无限 await oneshot。
  2. 解除阻塞的唯一路径是 daemon 退出:pending 请求只在 reader_task 读到 EOF/错误(daemon 崩溃或关 stdout)时被 reject。daemon 存活但不响应(单请求卡死、索引任务独占、内部死锁)时请求永不返回。
  3. 可用性检查不探活workspace_search_daemon_available() 只检查二进制文件存在,不 ping daemon,导致「daemon 已卡死」仍走 flashgrep 路径而不是降级到本地 rg。
  4. 对比异常:同文件里的 remote shell 分支都有显式超时(5s/30s),本地 workspace-search 分支反而裸 await,实现不一致。

影响

  • Agent 工作流被 Glob/Grep 挂起阻塞数分钟,需要手动取消。
  • 偶发且无明确报错,用户感知为「工具坏了」,排查成本高。
  • 挂起期间若并发多个 Glob/Grep(工具声明 is_concurrency_safe=true),多个调用同时堆积在 daemon 上。

Expected behavior

  • Glob/Grep 任意路径都有与 remote 分支一致的显式超时上限(30s 级别)。
  • daemon 不健康时工具自动降级到本地 rg 并记录 warn 日志,而不是无限挂起。
  • 超时错误信息可操作(含 daemon 状态与降级提示)。

建议修复

  1. 给 RPC 调用加超时(核心)RepoSession::search/glob/status/task_status/index_build/rebuild 传合理超时(如 10s~30s)。超时后错误返回,并利用已有 send_request_with_restart_timeout 机制触发 daemon 重启(should_restart_daemon 目前只对 Io/closed 重启,需把超时错误纳入重启判定或降级路径)。
  2. 工具层超时 + 自动降级glob_tool.rs / grep_tool.rs 对 workspace-search 调用加 tokio::time::timeout 包装;超时/错误时已有降级逻辑会自动落到 spawn_blocking 本地 rg(该路径无此问题)。
  3. 探活 daemonworkspace_search_runtime_available() 或调用前对 daemon 做 ping/health 检查,避免在 daemon 不健康时仍选择 flashgrep 后端。
  4. 可观测性:为 search/glob RPC 增加耗时与超时计数日志(现有日志已有耗时字段,补超时分支即可)。

Environment, if relevant

BitFun commit: 4d3869859 (2026-08-14)
OS: Windows x64
FLASHGREP_DAEMON_BIN: C:\Users\wfwt\AppData\Local\BitFun\flashgrep\flashgrep-x86_64-pc-windows-msvc.exe
相关代码目录: src/crates/assembly/core/src/agentic/tools/implementations/{glob,grep}_tool.rs,
             src/crates/services/services-integrations/src/workspace_search/

Related files

  • src/crates/assembly/core/src/agentic/tools/implementations/glob_tool.rs
  • src/crates/assembly/core/src/agentic/tools/implementations/grep_tool.rs
  • src/crates/assembly/core/src/service/search/service.rs
  • src/crates/services/services-integrations/src/workspace_search/service.rs
  • src/crates/services/services-integrations/src/workspace_search/flashgrep/client.rs
  • src/crates/services/services-integrations/src/workspace_search/flashgrep/rpc_client.rs
  • src/crates/services/services-integrations/src/workspace_search/flashgrep/repo_session.rs

Environment, if relevant

No response

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions