Skip to content

Commit 429cd40

Browse files
committed
Select rather than spin when we need to block.
- 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
1 parent 30455ae commit 429cd40

File tree

3 files changed

+34
-34
lines changed

3 files changed

+34
-34
lines changed

src/clj_libssh2/error.clj

+1-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111
milliseconds for that timeout."
1212
(atom {:agent 10000
1313
:auth 10000
14-
:known-hosts 10000
15-
:session 10000}))
14+
:known-hosts 10000}))
1615

1716
(def error-messages
1817
"All of the error codes that are documented for libssh2 except for

src/clj_libssh2/session.clj

+11-11
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
[clj-libssh2.libssh2 :as libssh2]
55
[clj-libssh2.libssh2.session :as libssh2-session]
66
[clj-libssh2.authentication :refer [authenticate]]
7-
[clj-libssh2.error :as error :refer [handle-errors with-timeout]]
7+
[clj-libssh2.error :as error :refer [handle-errors]]
88
[clj-libssh2.known-hosts :as known-hosts]
99
[clj-libssh2.socket :as socket]))
1010

@@ -74,12 +74,12 @@
7474
([session]
7575
(destroy-session session "Shutting down normally." false))
7676
([session reason raise]
77-
(handle-errors nil
78-
(with-timeout :session
79-
(libssh2-session/disconnect (:session session) reason)))
80-
(handle-errors nil
81-
(with-timeout :session
82-
(libssh2-session/free (:session session))))
77+
(socket/block session
78+
(handle-errors session
79+
(libssh2-session/disconnect (:session session) reason)))
80+
(socket/block session
81+
(handle-errors session
82+
(libssh2-session/free (:session session))))
8383
(when raise
8484
(throw (ex-info reason {:session session})))))
8585

@@ -93,10 +93,10 @@
9393
Return:
9494
9595
0 on success. Throws an exception on failure."
96-
[{session :session socket :socket :as s}]
97-
(handle-errors s
98-
(with-timeout :session
99-
(libssh2-session/handshake session socket))))
96+
[session]
97+
(socket/block session
98+
(handle-errors session
99+
(libssh2-session/handshake (:session session) (:socket session)))))
100100

101101
(defn close
102102
"Disconnect an SSH session and discard the session.

src/clj_libssh2/socket.clj

+22-21
Original file line numberDiff line numberDiff line change
@@ -69,40 +69,41 @@
6969
([session]
7070
(wait session (System/currentTimeMillis)))
7171
([session start-time]
72-
(let [ms-until-next-keepalive (* (send-keepalive session) 1000)
73-
block-directions (libssh2-session/block-directions (:session session))
74-
block-for-read (boolean (bit-and block-directions libssh2/SESSION_BLOCK_INBOUND))
75-
block-for-write (boolean (bit-and block-directions libssh2/SESSION_BLOCK_OUTBOUND))
76-
libssh2-timeout-ms (libssh2-session/get-timeout (:session session))
77-
select-until (partial select session block-for-read block-for-write)
78-
select-result (cond (and (< 0 libssh2-timeout-ms)
79-
(or (= 0 ms-until-next-keepalive)
80-
(> ms-until-next-keepalive libssh2-timeout-ms)))
81-
(let [elapsed (- (System/currentTimeMillis) start-time)]
82-
(when (> elapsed libssh2-timeout-ms)
83-
(handle-errors session libssh2/ERROR_TIMEOUT))
84-
(select-until (- libssh2-timeout-ms elapsed)))
72+
(when (and session (:session session) (> 0 (:socket session)))
73+
(let [ms-until-next-keepalive (* (send-keepalive session) 1000)
74+
block-directions (libssh2-session/block-directions (:session session))
75+
block-for-read (boolean (bit-and block-directions libssh2/SESSION_BLOCK_INBOUND))
76+
block-for-write (boolean (bit-and block-directions libssh2/SESSION_BLOCK_OUTBOUND))
77+
libssh2-timeout-ms (libssh2-session/get-timeout (:session session))
78+
select-until (partial select session block-for-read block-for-write)
79+
select-result (cond (and (< 0 libssh2-timeout-ms)
80+
(or (= 0 ms-until-next-keepalive)
81+
(> ms-until-next-keepalive libssh2-timeout-ms)))
82+
(let [elapsed (- (System/currentTimeMillis) start-time)]
83+
(when (> elapsed libssh2-timeout-ms)
84+
(handle-errors session libssh2/ERROR_TIMEOUT))
85+
(select-until (- libssh2-timeout-ms elapsed)))
8586

86-
(< 0 ms-until-next-keepalive)
87-
(select-until ms-until-next-keepalive)
87+
(< 0 ms-until-next-keepalive)
88+
(select-until ms-until-next-keepalive)
8889

89-
:else
90-
(select-until 0))]
91-
(when (>= 0 select-result)
92-
(handle-errors session libssh2/ERROR_TIMEOUT)))))
90+
:else
91+
(select-until 0))]
92+
(when (>= 0 select-result)
93+
(handle-errors session libssh2/ERROR_TIMEOUT))))))
9394

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

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

0 commit comments

Comments
 (0)