Skip to content

Commit

Permalink
Select rather than spin when we need to block.
Browse files Browse the repository at this point in the history
- Move some calls from `with-timeout` to `block`.
- Make `socket/wait` slightly more robust against partially "up" or
  "down" sessions.
- Fix a seconds v milliseconds bug.

Fixes: #4
  • Loading branch information
conormcd committed Jan 24, 2016
1 parent 30455ae commit 429cd40
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 34 deletions.
3 changes: 1 addition & 2 deletions src/clj_libssh2/error.clj
Expand Up @@ -11,8 +11,7 @@
milliseconds for that timeout."
(atom {:agent 10000
:auth 10000
:known-hosts 10000
:session 10000}))
:known-hosts 10000}))

(def error-messages
"All of the error codes that are documented for libssh2 except for
Expand Down
22 changes: 11 additions & 11 deletions src/clj_libssh2/session.clj
Expand Up @@ -4,7 +4,7 @@
[clj-libssh2.libssh2 :as libssh2]
[clj-libssh2.libssh2.session :as libssh2-session]
[clj-libssh2.authentication :refer [authenticate]]
[clj-libssh2.error :as error :refer [handle-errors with-timeout]]
[clj-libssh2.error :as error :refer [handle-errors]]
[clj-libssh2.known-hosts :as known-hosts]
[clj-libssh2.socket :as socket]))

Expand Down Expand Up @@ -74,12 +74,12 @@
([session]
(destroy-session session "Shutting down normally." false))
([session reason raise]
(handle-errors nil
(with-timeout :session
(libssh2-session/disconnect (:session session) reason)))
(handle-errors nil
(with-timeout :session
(libssh2-session/free (:session session))))
(socket/block session
(handle-errors session
(libssh2-session/disconnect (:session session) reason)))
(socket/block session
(handle-errors session
(libssh2-session/free (:session session))))
(when raise
(throw (ex-info reason {:session session})))))

Expand All @@ -93,10 +93,10 @@
Return:
0 on success. Throws an exception on failure."
[{session :session socket :socket :as s}]
(handle-errors s
(with-timeout :session
(libssh2-session/handshake session socket))))
[session]
(socket/block session
(handle-errors session
(libssh2-session/handshake (:session session) (:socket session)))))

(defn close
"Disconnect an SSH session and discard the session.
Expand Down
43 changes: 22 additions & 21 deletions src/clj_libssh2/socket.clj
Expand Up @@ -69,40 +69,41 @@
([session]
(wait session (System/currentTimeMillis)))
([session start-time]
(let [ms-until-next-keepalive (* (send-keepalive session) 1000)
block-directions (libssh2-session/block-directions (:session session))
block-for-read (boolean (bit-and block-directions libssh2/SESSION_BLOCK_INBOUND))
block-for-write (boolean (bit-and block-directions libssh2/SESSION_BLOCK_OUTBOUND))
libssh2-timeout-ms (libssh2-session/get-timeout (:session session))
select-until (partial select session block-for-read block-for-write)
select-result (cond (and (< 0 libssh2-timeout-ms)
(or (= 0 ms-until-next-keepalive)
(> ms-until-next-keepalive libssh2-timeout-ms)))
(let [elapsed (- (System/currentTimeMillis) start-time)]
(when (> elapsed libssh2-timeout-ms)
(handle-errors session libssh2/ERROR_TIMEOUT))
(select-until (- libssh2-timeout-ms elapsed)))
(when (and session (:session session) (> 0 (:socket session)))
(let [ms-until-next-keepalive (* (send-keepalive session) 1000)
block-directions (libssh2-session/block-directions (:session session))
block-for-read (boolean (bit-and block-directions libssh2/SESSION_BLOCK_INBOUND))
block-for-write (boolean (bit-and block-directions libssh2/SESSION_BLOCK_OUTBOUND))
libssh2-timeout-ms (libssh2-session/get-timeout (:session session))
select-until (partial select session block-for-read block-for-write)
select-result (cond (and (< 0 libssh2-timeout-ms)
(or (= 0 ms-until-next-keepalive)
(> ms-until-next-keepalive libssh2-timeout-ms)))
(let [elapsed (- (System/currentTimeMillis) start-time)]
(when (> elapsed libssh2-timeout-ms)
(handle-errors session libssh2/ERROR_TIMEOUT))
(select-until (- libssh2-timeout-ms elapsed)))

(< 0 ms-until-next-keepalive)
(select-until ms-until-next-keepalive)
(< 0 ms-until-next-keepalive)
(select-until ms-until-next-keepalive)

:else
(select-until 0))]
(when (>= 0 select-result)
(handle-errors session libssh2/ERROR_TIMEOUT)))))
:else
(select-until 0))]
(when (>= 0 select-result)
(handle-errors session libssh2/ERROR_TIMEOUT))))))

(defmacro block
"Turn a non-blocking call that returns EAGAIN into a blocking one."
[session & body]
`(let [start-time# (-> (System/currentTimeMillis) (/ 1000.0) Math/round)]
`(let [start-time# (System/currentTimeMillis)]
(while (= libssh2/ERROR_EAGAIN (do ~@body))
(handle-errors ~session
(wait ~session start-time#)))))

(defmacro block-return
"Similar to block, but for functions that return a pointer"
[session & body]
`(let [start-time# (-> (System/currentTimeMillis) (/ 1000.0) Math/round)]
`(let [start-time# (System/currentTimeMillis)]
(loop [result# (do ~@body)]
(if (nil? result#)
(let [errno# (libssh2-session/last-errno (:session ~session))]
Expand Down

0 comments on commit 429cd40

Please sign in to comment.