Repository navigation
ssh_executor: Execute commands without creating stdin file - #67
Merged
Merged
Conversation
SSHClient.exec_command() returns a stdin file object, which _execute() and is_active() never use. When it is garbage collected, its close() calls Channel.shutdown_write(), which builds the EOF message under the channel lock but sends it only after releasing the lock. If the transport thread handles the server's channel CLOSE in that window, it sends EOF and CLOSE of its own, and our EOF reaches the server after the CLOSE. OpenSSH sshd (seen with 10.2) treats this as a protocol error: channel_by_id: 1: bad id: channel free Disconnecting user root ...: ieof packet referred to nonexistent channel 1 and drops the whole connection, killing every command running on it. With several threads sharing one connection, this shows up as random commands failing with exit code -1. Open the session channel directly instead, run the command on it and read only stdout and stderr, so no stdin file object is ever created. Close the channel explicitly once the command completes; Channel.close() sends EOF and CLOSE together, in order, and only if the channel is not closed already. Signed-off-by: Robert Baldyga <robert.baldyga@unvertical.com>
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.
SSHClient.exec_command() returns a stdin file object, which _execute() and is_active() never use. When it is garbage collected, its close() calls Channel.shutdown_write(), which builds the EOF message under the channel lock but sends it only after releasing the lock. If the transport thread handles the server's channel CLOSE in that window, it sends EOF and CLOSE of its own, and our EOF reaches the server after the CLOSE. OpenSSH sshd (seen with 10.2) treats this as a protocol error:
channel_by_id: 1: bad id: channel free
Disconnecting user root ...: ieof packet referred to nonexistent channel 1
and drops the whole connection, killing every command running on it. With several threads sharing one connection, this shows up as random commands failing with exit code -1.
Open the session channel directly instead, run the command on it and read only stdout and stderr, so no stdin file object is ever created. Close the channel explicitly once the command completes; Channel.close() sends EOF and CLOSE together, in order, and only if the channel is not closed already.