[Bug] Remote SSH workspace: Write/Edit permanently fail with "Limit exceeded: handle limit reached" after long session (russh-sftp client-side handle leak)
- Dominant language
- Rust
- Stars
- 2.2k
- Forks
- 229
- Avg merge
- 2h 46m
- Merged PRs (30d)
- 577
Description
### Summary
远程 SSH 工作区在长会话高强度使用文件工具后,所有 `Write`/`Edit` 持续失败,报 `Limit exceeded: handle limit reached`,等待 30 分钟以上不自愈,只能重启桌面端恢复。同期 `Read`/`Glob`/`Grep`/终端均正常。
定位证据指向 russh-sftp 客户端侧句柄表泄漏(见下)。
### Area
Desktop app
### Reproduction or evidence
1. 连接远程 SSH 工作区,长时间高频使用文件工具(大量分块 Read、多次 Write/Edit);
2. 累计足够多打开/关闭循环后触发;
3. 此后所有 `Write`/`Edit` 持续失败,间隔 30 分钟以上的多次重试均不恢复;
4. `Read`/`Glob`/`Grep`/`ExecCommand` 全部正常。
`Write`:
```
Tool 'Write' failed (execution_error): Tool error: Failed to write file:
Failed to create remote file '/path/to/workspace/.bitfun/tmp/write_xxxxxxxx.tmp':
Limit exceeded: handle limit reached
```
`Edit`(内置 re-read 步骤即失败):
```
File /path/to/file.py could not be re-read before editing
(Tool error: Failed to read file: Failed to open remote file '/path/to/file.py':
Limit exceeded: handle limit reached)
```
注意不对称性:普通 `Read` 工具同一时刻仍能成功打开同一文件,而 `Edit` 内部 re-read 与 `Write` 的新建 open 失败——疑似读/写两条 SFTP 会话中写路径的句柄表先耗尽。
1. `handle limit reached` 错误串在 bitfun-desktop 二进制 strings 中与 `russh_sftp::client::rawsession`、`attempt to close more handles than exist` 相邻——错误来自 **russh-sftp 客户端侧会话句柄表**,不是服务端 sshd(远端 sftp-server 进程仅 7 个 fd,远未达任何限制)。
2. 上游生态已确认同类机制:remotefs-rs-ssh PR#22(https://github.com/remotefs-rs/remotefs-rs-ssh/pull/22)原文:
> russh-sftp's `File::drop` closes handles via `close_nowait`, which frees the handle server-side but never decrements the client's open-handle counter. Reads (one handle per chunk) and writes (one handle per upload) relied on `Drop`, so the counter climbed monotonically until the negotiated limit was reached, failing later operations with `Limit exceeded: Handle limit reached`.
与本例现象逐点吻合:计数单调增长、达到协商上限后新 open 全失败、不自愈。
- SFTP 文件句柄关闭使用 awaited close/shutdown(等 close 响应后再递减客户端计数器),不依赖 `Drop`/`close_nowait`;
- 读路径若按 chunk 开关 handle,考虑单 handle + seek 复用;
- 收到 `Handle limit reached` 时自动重建 SFTP 会话(句柄表随会话重置)实现自愈,而不是让错误永久驻留;
- 建议在日志中输出 open-handle 计数与上限,便于确认泄漏速率。
### Environment, if relevant
- BitFun 桌面端 **0.2.18**(macOS,Tauri/Rust 后端)
- 工作区类型:**Remote SSH**(目标 macOS 主机,OpenSSH + sftp-server)
- 桌面进程连续运行 1 天 9 小时+;触发前约 1.5~2 小时高强度使用(数十次大文件分块 Read + 若干次 Write/Edit)
- 期间存在两条 sftp-server 进程(不同时间各起一条),疑似读/写走不同 SFTP 通道
Contributor guide
Research direction
Locate the Rust remote SSH/SFTP client code and its handle lifecycle, using the `russh_sftp::client::rawsession` evidence and upstream remotefs-rs-ssh PR #22 as starting points. Reproduce the long-session failure with repeated Read/Write/Edit operations, then verify that the chosen fix prevents handle exhaustion or recovers the SFTP session.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, tauri
- Domain
- desktop, networking
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 42/100