[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Bug#714606: help with fixing ruby-net-ssh: can't add a new key into hash during iteration during ssh.exec



On 14/04/15 at 15:12 +0200, Martin Steigerwald wrote:
> Am Dienstag, 14. April 2015, 14:39:04 schrieb David Suarez:
> > Hi,
> > 
> > 2015-04-14 13:00 GMT+02:00 Martin Steigerwald <ms@teamix.de>:
> > > Am Dienstag, 14. April 2015, 12:36:33 schrieb Martin Steigerwald:
> > >> Cc'ing the bug report as well, feel free to drop the cc for discussion on mailing list.
> > >> an each in session.rb, line 222.
> > >>
> > >>
> > >> Which looks quite central to the working of ruby-net-ssh to me
> > >>
> > >>     # This is called internally as part of #process. It dispatches any
> > >>     # available incoming packets, and then runs Net::SSH::Connection::Channel#process
> > >>     # for any active channels. If a block is given, it is invoked at the
> > >>     # start of the method and again at the end, and if the block ever returns
> > >>     # false, this method returns false. Otherwise, it returns true.
> > >>     def preprocess
> > >>       return false if block_given? && !yield(self)
> > >>       dispatch_incoming_packets
> > >>       channels.each { |id, channel| channel.process unless channel.closing? }
> > >>       return false if block_given? && !yield(self)
> > >>       return true
> > >>     end
> > >>
> > >>
> > >>
> > >> The calling site inside distkeys is:
> > >>
> > >> https://github.com/teamix/distkeys/blob/master/distkeys#L174
> > >>
> > 
> > You are right, 'channels' Hash is modified inside 'channels.each' call.
> > 
> > > I am not sure whether it is a work-around or whether it is a valid
> > > contraint to be taken into account when using ruby-net-ssh. To me it
> > > feels like a work-around, but well… if it works this way.
> > >
> > > If you still have an idea how to fix it in ruby-net-ssh, please tell me.
> > 
> > Seems like a valid constrain, due that the problem arise when you are
> > trying to open a new channel (ssh.exec!) inside the processing block
> > of the another channel (sftp.lstat) in the same ssh session.
> > 
> > One fix could be that instead os reusing the actual ssh connection to
> > open the sftp one ""@sftp = Net::SFTP::Session.new(@ssh)"", create a
> > new sftp connection ""Net::SFTP.start(host, user, options)"".
> 
> Thanks.
> 
> I now just finish the sftp operation before doing the ssh.exec calls and
> this appears to work. Just uploaded distkeys-1.1 to github including 1.1
> debian package source. This also fixes the same for the replacing of
> authorized_keys with authorized_keys-new which was racy before due to
> work-arounding this issue by deleting first and then sftp.rename() which
> in current ruby-net-sftp cannot overwrite a file.
> 
> This appears to work just nice. And I also documented this behavior in
> the script.
> 
> Will test internally for a while and then probably reapproach with request
> for sponsoring for distkeys. Maybe one day will get distkeys into Debian,
> I think its quite useful, cause it can put ssh keys to hosts behind
> firewalls using ssh port forwarding automatically. After Jessie release :).
> 
> As for this bug, if you think its a valid constraint, feel free to close it.
> 
> I still think it would be good to at least have this documented somewhere
> with ruby-net-ssh, cause the interference between ssh and sftp calls are not
> that obvious but due to a implementation detail.
> 
> But I can try to send a documentation patch upstream.

Hi,

I don't think that this is a bug in ruby-net-ssh, as the inability to
modify a hash during iteration is a Ruby limitation. See e.g:

irb(main):005:0> h = { :a => 1}
=> {:a=>1}
irb(main):006:0> h.each_pair { |k, v| h[:b] = 2 }
RuntimeError: can't add a new key into hash during iteration
	from (irb):6:in `block in irb_binding'
	from (irb):6:in `each_pair'
	from (irb):6
	from /usr/bin/irb:11:in `<main>'

I'm closing this bug.

Lucas


Reply to: