[
https://issues.apache.org/jira/browse/SSHD-1334?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Thomas Wolf resolved SSHD-1334.
-------------------------------
Fix Version/s: 2.13.0
Resolution: Fixed
Was fixed in [https://github.com/apache/mina-sshd/issues/427] .
> DefaultScpClient::upload(InputStream, ...) will always hit the exit status
> timeout
> ----------------------------------------------------------------------------------
>
> Key: SSHD-1334
> URL: https://issues.apache.org/jira/browse/SSHD-1334
> Project: MINA SSHD
> Issue Type: Bug
> Affects Versions: 2.10.0
> Reporter: Ryan Livingston
> Priority: Major
> Fix For: 2.13.0
>
> Attachments: file-based.txt, stream-based.txt
>
>
> When attempting to upload/scp a byte stream using the below method, the main
> thread will always block until the exit status timeout is reached.
> {code:java}
> DefaultScpClient::upload(InputStream local, String remote, long
> size,Collection<PosixFilePermission> perms, ScpTimestampCommandDetails
> time){code}
> It appears this is the case because the _handleCommandExitStatus(cmd,
> channel)_ is called before the In/Out channels are auto-closed by the
> try-with-resources block, and thus the EOF is not sent to the remote prior to
> handling the exit status. The current implementation always times out first
> and then sends an EOF while closing the channels.
> Using the API to send based on file paths will invoke
> _DefaultScpClient::runUpload()_ which first closes the channel resources and
> then waits for the exit status. This API works well without the exit status
> blocking the thread.
> I have overridden the default client to ignore the exit status result, and
> there is a dedicated property to adjust this timeout. Though, this is not
> really a solution to this issue.
> I attempted to override and close the channels first prior to handling the
> exit status like {_}runUpload(){_}, but this introduced some async issues
> when processing some remaining inbound messages from the remote after the
> pipe is closed.
> This issue is persistent on remote SSH servers running with CentOS and MacOS.
> This example is being run on MacOS 13.3.1 with a remote SSH server that has
> no explicit SSH configuration.
> Path based logging:
> {code:java}
> 2023-08-02 14:17:50 DEBUG ScpHelper:597 -
> sendStream(ScpHelper[ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22]])[/Users/ryanlivingston/tmp/testfile.txt]
> command='C0644 9 testfile.txt' ACK=0
> 2023-08-02 14:17:50 DEBUG ChannelExec:940 - sendEof(ChannelExec[id=0,
> recipient=0]-ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])
> SSH_MSG_CHANNEL_EOF (state=Opened)
> 2023-08-02 14:17:50 DEBUG ClientSessionImpl:1402 -
> encode(ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22]) packet #11
> sending command=96[SSH_MSG_CHANNEL_EOF] len=5
> 2023-08-02 14:17:50 DEBUG Nio2Session:179 -
> writeBuffer(Nio2Session[local=/127.0.0.1:54429,
> remote=localhost/127.0.0.1:22]) writing 36 bytes
> 2023-08-02 14:17:50 DEBUG DefaultScpClient:155 -
> runUpload(ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])
> /Users/ryanlivingston/tmp/testfile2.txt =>
> [/Users/ryanlivingston/tmp/testfile.txt] - failed
> (UnsupportedOperationException) to close file
> system=sun.nio.fs.MacOSXFileSystem@9ebe38b: null
> 2023-08-02 14:17:50 DEBUG ClientSessionImpl:544 -
> doHandleMessage(ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])
> process #16 SSH_MSG_CHANNEL_EOF
> 2023-08-02 14:17:50 DEBUG ChannelExec:873 - handleEof(ChannelExec[id=0,
> recipient=0]-ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])
> SSH_MSG_CHANNEL_EOF
> 2023-08-02 14:17:50 DEBUG ClientSessionImpl:544 -
> doHandleMessage(ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])
> process #17 SSH_MSG_CHANNEL_REQUEST
> 2023-08-02 14:17:50 DEBUG ChannelExec:271 -
> handleChannelRequest(ChannelExec[id=0,
> recipient=0]-ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])
> SSH_MSG_CHANNEL_REQUEST exit-status wantReply=false
> 2023-08-02 14:17:50 DEBUG ExitStatusChannelRequestHandler:50 -
> processRequestValue(ChannelExec[id=0,
> recipient=0]-ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])
> status=0
> 2023-08-02 14:17:50 DEBUG ExitStatusChannelRequestHandler:59 -
> process(ChannelExec[id=0,
> recipient=0]-ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])[exit-status]
> wantReply=false: 0
> 2023-08-02 14:17:50 DEBUG ChannelExec:114 - notifyEvent(ChannelExec[id=0,
> recipient=0]-ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22]):
> exit-status
> 2023-08-02 14:17:50 DEBUG ExitStatusChannelRequestHandler:101 -
> notifyStateChanged(ChannelExec[id=0,
> recipient=0]-ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])[exit-status]
> event=exit-status
> 2023-08-02 14:17:50 DEBUG ChannelExec:345 - sendResponse(ChannelExec[id=0,
> recipient=0]-ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])
> request=exit-status result=ReplySuccess, want-reply=false
> 2023-08-02 14:17:50 DEBUG ChannelExec:247 - waitFor(ChannelExec[id=0,
> recipient=0]-ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])
> mask=[CLOSED, EXIT_STATUS] - exit status=0
> 2023-08-02 14:17:50 DEBUG ClientSessionImpl:544 -
> doHandleMessage(ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])
> process #18 SSH_MSG_CHANNEL_CLOSE
> 2023-08-02 14:17:50 DEBUG DefaultScpClient:176 -
> handleCommandExitStatus(ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])
> cmd='scp -t -- /Users/ryanlivingston/tmp/testfile2.txt', waited=636667
> nanos, events=[EOF, EXIT_STATUS, OPENED]
> 2023-08-02 14:17:50 DEBUG DefaultScpClient:206 -
> handleCommandExitStatus(ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])
> cmd='scp -t -- /Users/ryanlivingston/tmp/testfile2.txt', exit-status=OK
> {code}
> Stream based logging:
> {code:java}
> 2023-08-02 14:32:57 DEBUG ScpHelper:597 -
> sendStream(ScpHelper[ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22]])[scp
> -p -t -- /Users/ryanlivingston/tmp/testfile.txt] command='C0666 9
> testfile.txt' ACK=0 2023-08-02 14:32:57 DEBUG ClientSessionImpl:544 -
> doHandleMessage(ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])
> process #15 SSH_MSG_CHANNEL_DATA 2023-08-02 14:32:57 DEBUG LocalWindow:87 -
> Consume LocalWindow[client](ChannelExec[id=0,
> recipient=0]-ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22]) by 1
> down to 2097148 2023-08-02 14:32:57 DEBUG ChannelExec:788 -
> handleData(ChannelExec[id=0,
> recipient=0]-ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])
> SSH_MSG_CHANNEL_DATA len=1 2023-08-02 14:33:02 DEBUG DefaultScpClient:176 -
> handleCommandExitStatus(ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])
> cmd='scp -p -t -- /Users/ryanlivingston/tmp/testfile.txt', waited=5007089542
> nanos, events=[TIMEOUT, OPENED] 2023-08-02 14:33:02 DEBUG
> DefaultScpClient:206 -
> handleCommandExitStatus(ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])
> cmd='scp -p -t -- /Users/ryanlivingston/tmp/testfile.txt', exit-status=null
> 2023-08-02 14:33:02 DEBUG ChannelExec:940 - sendEof(ChannelExec[id=0,
> recipient=0]-ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])
> SSH_MSG_CHANNEL_EOF (state=Opened) 2023-08-02 14:33:02 DEBUG
> ClientSessionImpl:1402 -
> encode(ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22]) packet #12
> sending command=96[SSH_MSG_CHANNEL_EOF] len=5 2023-08-02 14:33:02 DEBUG
> Nio2Session:179 - writeBuffer(Nio2Session[local=/127.0.0.1:54518,
> remote=localhost/127.0.0.1:22]) writing 36 bytes 2023-08-02 14:33:02 DEBUG
> ChannelExec:107 - close(ChannelExec[id=0,
> recipient=0]-ClientSessionImpl[ryanlivingston@localhost/127.0.0.1:22])
> Closing gracefully {code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]