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

Add a timeout option to with-connection #12

Open
hugoduncan opened this issue Apr 23, 2012 · 5 comments
Open

Add a timeout option to with-connection #12

hugoduncan opened this issue Apr 23, 2012 · 5 comments

Comments

@hugoduncan
Copy link
Collaborator

with-connection does not currently allow a timeout specification for making a connection.

@rutchkiwi
Copy link

Hi! I've seen this issue in production, and it kills my app permanently when it hangs. Would you be open for a PR fixing this? Are there any specific issues that makes it hard? Thanks! :)

@xingzheone
Copy link

xingzheone commented Nov 21, 2017

If you check how the Util.createSocket is implemented, you will see that the timeout defines an upper limit of the connection only, not a lower limit, because the timeout is strangely not passed to an underlying Socket.Those 20 seconds is probably an OS-level default limit.To override it, try implementing the SocketFactory and attach it to the session using the Session.setSocketFactory.

链接 stackoverflow
please close

@lsh-0
Copy link

lsh-0 commented May 8, 2019

no timeout and hanging still present in 2019-05

@brianfay
Copy link

Not sure how to reproduce this issue, but I had a similar problem. All of the worker threads in my app were tied up in the with-connection call, rendering my app useless until restart.

Here's a potential workaround, in case it benefits anyone.

I noticed in the source that the Session protocol has a two-arity connect that includes a timeout parameter.

([session timeout] (.connect session timeout)))

It seems to work, but is not being used by thewith-connection macro.

We can just define our own alternative macro that uses the timeout parameter:

;; "ssh" here is an alias for clj-ssh.ssh, make sure you are requiring that in your ns declaration
(defmacro with-connection-timeout
    "Creates a context in which the session is connected. Ensures the session is
  disconnected on exit. Will timeout after the provided number of milliseconds if not succesfully connected."
    [session timeout & body]
    `(let [session# ~session timeout# ~timeout]
       (try
         (when-not (ssh/connected? session#)
           (ssh/connect session# timeout#))
         ~@body
         (finally
           (ssh/disconnect session#)))))

You can test this by trying to connect to a non-sftp host:

(let [agent (ssh/ssh-agent {})
        sess (ssh/session agent "google.com" {})]
    (with-connection-timeout sess 5000
      "something!"))

After 5 seconds, it will throw an exception: com.jcraft.jsch.JSchException with message "timeout: socket is not established"

However, do note that this timeout param only controls the time to connect to the socket.
If you do some long-running work inside the body, the timeout param will not prevent that.

For example, if this code connects successfully within 3 seconds, it will then execute the 9 second thread sleep before closing the connection and returning:

(with-connection-timeout sess 3000
  (Thread/sleep 9000)
  "this took at least 9 seconds to return")

@horttanainen
Copy link

Nice work @brianfay. Thank you

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

6 participants