GCWing / GCWing/OpenBitFun

[Bug] Remote SSH workspace: Write/Edit permanently fail with "Limit exceeded: handle limit reached" after long session (russh-sftp client-side handle leak)

Đang mở
#2,424 0 bình luận 0 reaction 0 người được giao Xem trên GitHub
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

Mở 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

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.