-
Notifications
You must be signed in to change notification settings - Fork 255
Description
This bug was first reported here, with the symptom of Capistrano prompting for the SSH password twice: capistrano/capistrano#1774
This got me thinking that perhaps the SSHKit connection pool is actually creating two connections instead of one. And in fact, this is indeed the case.
I added a puts statement to connection_pool.rb like this:
@@ -56,6 +56,7 @@ class SSHKit::Backend::ConnectionPool
def with(connection_factory, *args)
cache = find_cache(args)
conn = cache.pop || begin
+ puts "*** Opening new SSH connection with args: #{args.to_s}"
connection_factory.call(*args)
end
yield(conn)And then ran cap production deploy:check. Sure enough, two connections were opened.
The interesting thing is that args.to_s generates two different results. Since args.to_s is used to generate a key for the connection pool, this is why the pool thinks it needs to create two separate connections.
to_s is changing because SSHKit::Backend::Netssh::KnownHosts has mutable state and is changing state in between the two SSH executions. You can see that in the second case, my ~/.ssh/known_hosts has now been loaded and cached by KnownHosts, which changes its to_s output.
*** Opening new SSH connection with args: ["xx.xx.xx.xx", "deployer", {:user=>"deployer", :forward_agent=>true, :known_hosts=>#<SSHKit::Backend::Netssh::KnownHosts:0x007f9b78b0abb0 @_mutex=#<Thread::Mutex:0x007f9b78b0ab10>, @files={}>, :compression=>true, :keepalive=>true}]
.
.
.
*** Opening new SSH connection with args: ["xx.xx.xx.xx", "deployer", {:user=>"deployer", :forward_agent=>true, :known_hosts=>#<SSHKit::Backend::Netssh::KnownHosts:0x007f9b78b0abb0 @_mutex=#<Thread::Mutex:0x007f9b78b0ab10>, @files={"~/.ssh/known_hosts"=>#<SSHKit::Backend::Netssh::KnownHostsKeys:0x007f9b7a979b28 @_mutex=#<Thread::Mutex:0x007f9b7a979a88>, @path="/Users/mbrictson/.ssh/known_hosts", @hosts_keys={REDACTED...
I think we need to either:
- modify
KnownHosts#to_sto be a stable value; or - change how the pool key is calculated so that it is not sensitive to
KnownHosts#to_s
/cc @byroot