hierynomus / sshj

ssh, scp and sftp for java

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

"The handle is invalid." error when opening the 128th RemoteFile when using WinSSHD

vpartington opened this issue · comments

While running the integration tests for Overthere, which uses SSH/J for its SSH connections, the following exception is thrown when the 128th RemoteFile is opened for reading or writing when connecting to WinSSH version 5 or version 6:

Exception in thread "main" net.schmizz.sshj.sftp.SFTPException: The handle is invalid.
    at net.schmizz.sshj.sftp.Response.error(Response.java:113)
    at net.schmizz.sshj.sftp.Response.ensureStatusIs(Response.java:106)
    at net.schmizz.sshj.sftp.Response.ensureStatusPacketIsOK(Response.java:99)
    at net.schmizz.sshj.sftp.RemoteResource.close(RemoteResource.java:53)
    at sshj.ReadFileManyTimes.main(ReadFileManyTimes.java:37)

I've been able to reproduce the error using this standalone program:

package sshj;

import net.schmizz.sshj.SSHClient;
import net.schmizz.sshj.sftp.OpenMode;
import net.schmizz.sshj.sftp.RemoteFile;
import net.schmizz.sshj.sftp.RemoteFile.RemoteFileInputStream;
import net.schmizz.sshj.sftp.SFTPClient;
import net.schmizz.sshj.transport.verification.PromiscuousVerifier;

import com.google.common.io.ByteStreams;

import static com.google.common.collect.Sets.newHashSet;

public class ReadFileManyTimes {

    public static void main(String[] args) throws Exception {
        SSHClient c = new SSHClient();
        c.addHostKeyVerifier(new PromiscuousVerifier());

        try {
            c.connect("host);
            try {
                c.authPassword("username", "password");
                SFTPClient client = c.newSFTPClient();
                byte b[] = new byte[1024];
                for (int i = 1;; i++) {
                    RemoteFile rf = client.open("c:\\temp\\file.dat", newHashSet(OpenMode.READ));
                    try {
                        System.err.println("#" + i);
                        RemoteFileInputStream in = rf.new RemoteFileInputStream();
                        try {
                            ByteStreams.readFully(in, b);
                        } finally {
                            in.close();
                        }
                    } finally {
                        rf.close();
                    }
                }
            } finally {
                c.disconnect();
            }
        } finally {
            c.close();
        }
    }
}

I'm trying to figure out whether this is due to:

  1. A bug in Overthere, i.e. incorrect usage of the SSH/J API, or
  2. A bug in WinSSHD, or
  3. A bug in SSH/J

I've noticed that the problem does not appear when I move the opening of the RemoteFile into the loop so that would hint at a resource leak in the RemoteFile.close() method.

I hope I've provided enough informaton. If not, please let me know!

Regards, Vincent Partington.

@vpartington I assume you mean that it doesn't happen if you move the opening outside of the loop, it is now in the loop.

@vpartington Does this also happen with other SSH daemons? (OpenSSH?)

@hierynomus: This only occurs with WinSSHD and the problem does indeed disappear when I move the opening of the file to outside of the loop

But I can't do the generically because the mode (read/write/append, etc.) is also set when opening a file. And you'd think that closing the file (rf.close()) would release any resources that are allocated while opening it.

It seems like a bug in WinSSHD if this only occurs with that SSH server. The error message / stacktrace also seems to indicate this comes from the other side of the connection?

True, but the error could also be caused by some resource not being closed properly by the client, i.e. SSHJ or the code invoking SSHJ. I'd like to rule out those two possibilities first.

This is now fixed in master with #150.