[
https://issues.apache.org/jira/browse/SSHD-1352?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18144454#comment-18144454
]
perfah commented on SSHD-1352:
------------------------------
After looking into this further it appears to boil down to this:
The error message "client is closed" refers to the *SftpClient* and not the
{*}SshClient{*}. We have been using SftpFileSystem(Provider) but not SftpClient
directly, so from our perspective it may be considered an implementation detail
that SftpClient is indirectly used. SshClient is what we provide/configure for
the file system. Naturally, and without looking into the apache-mina codebase
you'd think the client here is the one you interact with, hence the confusion.
Tracking this down it appears that the two objects have distinct states, and
{{AbstractCloseable.State = Closed}} can be set separately for each, and
{{SessionHelper.exceptionCaught}} only applies to the SftpClient/ClientSession
as opposed to SshClient. When using {{{}SftpFileSystem(Provider){}}}, this is
further complicated by {{getClientSession().isOpen()}} being the only reliable
way to retrieve whether the SftpClient is open without client displacement.
Essentially only {{filesystem.getClientSession().isOpen()}} but not
{{sshClient.isOpen()}} can be used to determine whether the connection to go
down, or if a "client is closed" has occurred in our case. That is despite the
constructor signature {{SftpFileSystemProvider(SshClient client)}} making you
think otherwise.
I take it back that this is necessarily a bug or wrong, but it certainly
appears to be an API quirk that may cause confusion in the future. Whether you
think a change either in code or docs is warranted I will leave up to you.
*Original error:*
AbstractSftpClient.java:512
{code:java}
@Override
public CloseableHandle open(String path, Collection<OpenMode> options) throws
IOException {
if (!isOpen()) {
throw new IOException("open(" + path + ")[" + options + "] client is
closed");
}:{code}
*Exception handler unique to the* {*}SftpClient/ClientSession{*}{*}:{*}
ClientSessionImpl:
{code:java}
@Override
public void exceptionCaught(Throwable t) {
signalAuthFailure(t);
super.exceptionCaught(t);
} {code}
which calls AbstractCloseable.doCloseImmediately:
{code:java}
protected void doCloseImmediately() {
state.set(State.Closed);
closeFuture.setClosed();
}{code}
*isOpen():*
Both ClientSession.isOpen and SshClient.isOpen() uses the interface default for
Closeable/AbstractCloseable:
{code:java}
@Override
public final boolean isClosed() {
return state.get() == State.Closed;
}{code}
which checks state like expected, but only ClientSession handles the exception.
SshClient in contrast needs to be manually/explicitly closed/stop for the state
to reflect this.
> Paradoxical 'Client is closed' while SshClient::isOpen returns true
> -------------------------------------------------------------------
>
> Key: SSHD-1352
> URL: https://issues.apache.org/jira/browse/SSHD-1352
> Project: MINA SSHD
> Issue Type: Bug
> Affects Versions: 2.15.0
> Reporter: perfah
> Priority: Major
>
> We are seeing this stacktrace in our logs:
> {code:java}
> java.io.UncheckedIOException: java.io.IOException:
> readDir(/TLWPT/OrderRouting/To: 31) client is closed
> at
> org.apache.sshd.sftp.client.impl.SftpDirEntryIterator.load(SftpDirEntryIterator.java:181)
> at
> org.apache.sshd.sftp.client.impl.SftpDirEntryIterator.next(SftpDirEntryIterator.java:120)
> at
> org.apache.sshd.sftp.client.impl.SftpDirEntryIterator.next(SftpDirEntryIterator.java:45)
> at
> org.apache.sshd.sftp.client.fs.SftpPathIterator.nextEntry(SftpPathIterator.java:110)
> at
> org.apache.sshd.sftp.client.fs.SftpPathIterator.next(SftpPathIterator.java:104)
> at
> org.apache.sshd.sftp.client.fs.SftpPathIterator.next(SftpPathIterator.java:39)
> at java.base/java.nio.file.Files$2.next(Files.java:3802)
> at java.base/java.nio.file.Files$2.next(Files.java:3790)
> at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133){code}
>
> Yet our code for detecting that the client has been closed appears to not
> work (we see no recycled clients in our logs):
> {code:java}
> if (!clients.get(clientIdentity).isOpen()) {
> ...
> LOGGER.debug("Recycled SFTP Client: {}", clientIdentity);
> }{code}
> I made a brief investigation by asking an LLM about the most recent MINA
> repository, and according to it, the apparent contradiction can be resolved
> when you consider that _isOpen_ only reflects the status when you close it
> from the outside (implicitly via _try-with-resources_ or explicitly by doing
> {_}close(){_}), However, if the client is closed due to an internal reason
> (e.g. TCP connection is closed), the closed-status appears to not propagate
> up.
> Questions:
> 1. Can you confirm that this is the case? Or am I missing something?
> 2. Do you agree that _SshClient::isOpen_ should reflect the correct status
> even if the client is closed for an internal reason?
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]