[Bug] Remote SSH workspace: Write/Edit permanently fail with "Limit exceeded: handle limit reached" after long session (russh-sftp client-side handle leak)
- Ngôn ngữ chính
- Rust
- Star
- 2.3k
- Fork
- 231
- Merge trung bình
- 2 giờ 49 phút
- Pull request đã merge (30 ngày)
- 589
Mô tả
### 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 通道
Hướng dẫn đóng góp
Hướng nghiên cứu
Xác định mã của ứng dụng khách SSH/SFTP từ xa bằng Rust và vòng đời của các handle của nó, sử dụng bằng chứng từ `russh_sftp::client::rawsession` và PR #22 upstream của remotefs-rs-ssh làm điểm bắt đầu. Tái hiện lỗi của phiên dài bằng các thao tác Read/Write/Edit lặp lại, sau đó xác minh rằng fix đã chọn ngăn chặn việc cạn kiệt handle hoặc khôi phục phiên SFTP.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- rust, tauri
- Lĩnh vực
- desktop, networking
- Loại issue
- Lỗi
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức độ hoạt động
- Sôi nổi
- Độ rõ ràng
- Cần làm rõ
- Mức phù hợp với người mới
- 42/100