fix(connections): bound blocking SFTP calls and reuse the right cached session - #2843
Merged
Merged
Conversation
…ssion when the host changes
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.
Two defects in the SFTP transport behind "Remote Database File" (shipped in #2553, v0.69.0). Found while investigating #2831; both reproduced with a stall proxy in front of a real OpenSSH server. This is the area CLAUDE.md's "Cancelling a connect does not stop the driver" invariant governs, and both fixes follow it.
1. A dropped connection hangs for minutes, and Cancel does nothing
LibSSH2SFTPSessionrunsrealpath,statandreadas blocking libssh2 calls on one serial queue and never set a session timeout. When the peer dropped silently, a call blocked until TCP keepalive gave up (about eleven minutes),Cancelhad no effect becauseTask.cancel()cannot interrupt a blocking C call, andclose(), which runs on the same queue, waited behind it, so a disconnect stalled every other remote-file connection.The fix is the invariant's app-owned-deadline shape:
LibSSH2SFTPSession.opennow setslibssh2_session_set_timeoutto 60s, the same timeout the mobile SFTP client already uses. It bounds one operation, not the transfer: a healthy 32 KiB read returns in milliseconds, so only a dead peer reaches it. A stalledrealpathorreadthen returns a timeout error, the session is discarded, andclose()no longer waits.2. The cached session ignores a changed host
RemoteFileTransportManager.session(for:)cached one SFTP session per connection id and reused it with no check on where it pointed, and only a failed transfer discarded it. So a connection whose transfer never ran (a failing pre-connect script) kept its session, and editing the connection's Host then reused the old server's session: the old server's file was downloaded and stored under the new server's identity.Two changes:
Tests
RemoteFileSessionKeyTests: the server key ignores the path and the access mode, and changes with the host, port, or user. The blocking-timeout and discard-on-drop behaviour was validated against a stall proxy during the #2831 investigation; it is not unit-testable without that infrastructure, which is noted here rather than left silent.Verification