Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hang in Util.createSocket() if host is unreachable and a timeout is specified #450

Closed
NickstaDB opened this issue Dec 10, 2023 · 2 comments
Milestone

Comments

@NickstaDB
Copy link

I was debugging some code that uses JSch as follows:

Session session = new JSch().getSession(username, host, port);
session.setPassword(password);
session.connect(5000);

When the target host was unreachable, the program hung after main() had returned.

This is down to the createSocket() method of the class com.jcraft.jsch.Util.

https://github.com/mwiede/jsch/blob/master/src/main/java/com/jcraft/jsch/Util.java#L371

With a non-zero timeout, the method uses a thread to call new Socket(host, port), and the Thread.join(timeout) method is used to handle the timeout. If a connection is not established within the given time then Thread.interrupt() is called in an attempt to terminate the thread cleanly. This can lead to a hang, presumably until a default timeout occurs. I'm not sure if it differs between environments or Java versions but in my case (Windows, OpenJDK 19) the program hung for about 15 seconds after main() had returned.

The Util.createSocket() method also creates a bunch of seemingly redundant variables on the stack and heap when the timeout is non-zero.

The only reason I can think of for handling the timeout using a thread is that this is legacy code for Java < 1.4. A timeout parameter was introduced to the Socket.connect() method in Java 1.4. Assuming this is legacy code for <1.4 support, it's redundant, because the Util.createSocket() method also uses a lambda for the thread function and lambdas weren't supported until Java 8.

The Util.createSocket() method can therefore be replaced with something like the following - no need to use a thread or create a bunch of redundant variables:

static Socket createSocket(String host, int port, int timeout) throws JSchException {
    try {
        Socket socket = socket = new Socket();
        socket.connect(new InetSocketAddress(host, port), timeout);
        return socket;
    } catch(SocketTimeoutException ex) {
        throw new JSchException("timeout: " + ex, ex);
    } catch(Exception ex) {
        throw new JSchException("socket is not established: " + ex, ex);
    }
}

I'm not sure if there's some other reason for using a thread, or if there are edge cases where my suggestion wouldn't work. Happy to submit a PR to clean this method up.

norrisjeremy added a commit to norrisjeremy/jsch that referenced this issue Dec 11, 2023
…d since Java 1.4 instead of using old method of creating a separate thread and joining to that thread with timeout.
@norrisjeremy
Copy link
Contributor

Hi @NickstaDB,

Please see #451 that I have opened.

Thanks,
Jeremy

@NickstaDB
Copy link
Author

Nice, looks good, thanks!

@mwiede mwiede added this to the 0.2.14 milestone Dec 14, 2023
@mwiede mwiede closed this as completed Dec 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants