fix(sftp): send channel EOF+CLOSE when the SFTP session ends (fixes sshj/Cyberduck hang)#1
Closed
Yaminyam wants to merge 1 commit into
Closed
Conversation
The SFTP subsystem ran `russh_sftp::server::run()` which spawned the SFTP request loop on a detached task and returned immediately, so the handler never sent the server-side channel EOF/CLOSE after the session finished (unlike the shell/exec/SCP paths, which do). Clients that block on the SSH channel-close handshake — notably sshj/JSch (Cyberduck, PyCharm, IntelliJ) — then wait for a CLOSE that never arrives and hang for ~30s before timing out. OpenSSH `sftp`/FileZilla tolerate the missing CLOSE, which is why the problem only showed up with sshj-based clients. - bssh-russh-sftp: `run_with_config` no longer spawns internally; it runs the request loop inline and returns on client EOF, so the caller can observe completion and clean up the channel. - handler: run the SFTP session on our own task and, when it ends, send `handle.eof()` + `handle.close()` (mirroring the shell/exec/SCP paths). Also close the channel on the user-info error paths. Reproduced with an sshj 0.38 client (`canonicalize` + `stat` + `ls` + close): before, the `SFTPClient.close()` timed out after 30s; after, the session completes and closes in ~1s. OpenSSH `sftp` and paramiko continue to work unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Owner
Author
|
Re-targeting to lablup/bssh (upstream). See the new PR there. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Fixes lablup#215. sshj/JSch-based SFTP clients (Cyberduck, PyCharm/IntelliJ) hang ~30s then fail against
bssh-server, while OpenSSHsftp/FileZilla work fine.Root cause: the SFTP subsystem ran
russh_sftp::server::run(), which spawned the request loop on a detached task and returned immediately — so when the session ended, the handler never sent the server-side channel EOF/CLOSE (unlike shell/exec/SCP). OpenSSH/FileZilla tolerate the missing CLOSE; sshj/JSch strictly wait for the server'sSSH_MSG_CHANNEL_CLOSE, soSFTPClient.close()blocks until its 30s timeout.Fix
bssh-russh-sftp:run_with_configno longertokio::spawns internally — runs the loop inline and returns on client EOF.run()is only called from the server handler.handle.eof()+handle.close()(mirroring shell/exec/SCP). Also close on user-info error paths.Verification
Minimal sshj 0.38 client (
canonicalize→stat→ls→close): ~30s → ~1s. Regression: OpenSSHsftp(ls/get/put fine), paramiko (fine),cargo test -p bssh-russh-sftp(passes).