Skip to content

Commit 692a5f4

Browse files
authored
Merge pull request #487 from azrle/fix/pool_keepalive
Fix closed connection in pool
2 parents 820763d + c499228 commit 692a5f4

File tree

3 files changed

+31
-5
lines changed

3 files changed

+31
-5
lines changed

Vagrantfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ VAGRANTFILE_API_VERSION = "2"
22

33
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
44
config.vm.box = 'hashicorp/precise64'
5+
config.vm.provision "shell", inline: <<-SHELL
6+
echo 'ClientAliveInterval 1' >> /etc/ssh/sshd_config
7+
echo 'ClientAliveCountMax 1' >> /etc/ssh/sshd_config
8+
service ssh restart
9+
SHELL
510

611
json_config_path = File.join("test", "boxes.json")
712
list = File.open(json_config_path).read

lib/sshkit/backends/connection_pool/cache.rb

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ def push(conn)
3636
def evict
3737
# Peek at the first connection to see if it is still fresh. If so, we can
3838
# return right away without needing to use `synchronize`.
39-
first_expires_at, _connection = connections.first
40-
return if first_expires_at.nil? || fresh?(first_expires_at)
39+
first_expires_at, first_conn = connections.first
40+
return if (first_expires_at.nil? || fresh?(first_expires_at)) && !closed?(first_conn)
4141

4242
connections.synchronize do
43-
fresh, stale = connections.partition do |expires_at, _|
44-
fresh?(expires_at)
43+
fresh, stale = connections.partition do |expires_at, conn|
44+
fresh?(expires_at) && !closed?(conn)
4545
end
4646
connections.replace(fresh)
4747
stale.each { |_, conn| closer.call(conn) }
@@ -71,6 +71,13 @@ def fresh?(expires_at)
7171
end
7272

7373
def closed?(conn)
74-
conn.respond_to?(:closed?) && conn.closed?
74+
return true if conn.respond_to?(:closed?) && conn.closed?
75+
# test if connection is alive
76+
conn.process(0) if conn.respond_to?(:process)
77+
return false
78+
rescue IOError => e
79+
# connection is closed by server
80+
return true if e.message == 'closed stream'
81+
raise
7582
end
7683
end

test/functional/backends/test_netssh.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,20 @@ def test_interaction_handler
212212
end.run
213213
assert_equal("Enter Data\nCaptured SOME DATA", captured_command_result)
214214
end
215+
216+
def test_connection_pool_keepalive
217+
# ensure we enable connection pool
218+
SSHKit::Backend::Netssh.pool.idle_timeout = 10
219+
Netssh.new(a_host) do |_host|
220+
test :false
221+
end.run
222+
sleep 2.5
223+
captured_command_result = nil
224+
Netssh.new(a_host) do |_host|
225+
captured_command_result = capture(:echo, 'some_value')
226+
end.run
227+
assert_equal "some_value", captured_command_result
228+
end
215229
end
216230

217231
end

0 commit comments

Comments
 (0)