Your message dated Thu, 28 Jul 2016 08:49:53 +0200
with message-id <[email protected]>
and subject line Re: Bug#714606: help with fixing ruby-net-ssh: can't add a new 
key into hash during iteration during ssh.exec
has caused the Debian Bug report #714606,
regarding ruby-net-ssh: can't add a new key into hash during iteration during 
ssh.exec
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
714606: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=714606
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: ruby-net-ssh
Version: 1:2.5.2-2
Severity: normal

Dear Maintainer,

I am currently packaging our own distkeys key distribution ruby script
(see #712787 RFS: distkeys/1.0 -- distribute SSH keys).

However it only works with Ruby 1.8 for now, as with Ruby 1.9 I get a error
back from ruby-net-ssh when trying to add or remove a key:

./distkeys -K somekey.pub -H somehost add

Host: somehost
Connecting to host somehost (user: ms, port: 9999)...
Opening SFTP session...
Key somekey added.
Creating a backup to .ssh/authorized_keys-2013-07-01.bak if not already done 
today...
Uploading keys to .ssh/authorized_keys-new...
File does exist and has correct size, moving to .ssh/authorized_keys...
/usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:296:in `[]=': can't add 
a new key into hash during iteration (RuntimeError)
        from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:296:in 
`open_channel'
        from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:320:in 
`exec'
        from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:354:in 
`exec!'
        from ./distkeys:206:in `block in commit'
        from 
/var/lib/gems/1.9.1/gems/net-sftp-2.1.2/lib/net/sftp/request.rb:87:in `call'
        from 
/var/lib/gems/1.9.1/gems/net-sftp-2.1.2/lib/net/sftp/request.rb:87:in 
`respond_to'
        from 
/var/lib/gems/1.9.1/gems/net-sftp-2.1.2/lib/net/sftp/session.rb:948:in 
`dispatch_request'
        from 
/var/lib/gems/1.9.1/gems/net-sftp-2.1.2/lib/net/sftp/session.rb:911:in 
`when_channel_polled'
        from /usr/lib/ruby/vendor_ruby/net/ssh/connection/channel.rb:311:in 
`call'
        from /usr/lib/ruby/vendor_ruby/net/ssh/connection/channel.rb:311:in 
`process'
        from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:214:in 
`block in preprocess'
        from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:214:in 
`each'
        from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:214:in 
`preprocess'
        from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:197:in 
`process'
        from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:161:in 
`block in loop'
        from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:161:in 
`loop'
        from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:161:in 
`loop'
        from 
/var/lib/gems/1.9.1/gems/net-sftp-2.1.2/lib/net/sftp/session.rb:802:in `loop'
        from 
/var/lib/gems/1.9.1/gems/net-sftp-2.1.2/lib/net/sftp/request.rb:72:in `wait'
        from 
/var/lib/gems/1.9.1/gems/net-sftp-2.1.2/lib/net/sftp/session.rb:842:in 
`wait_for'
        from 
/var/lib/gems/1.9.1/gems/net-sftp-2.1.2/lib/net/sftp/session.rb:320:in `lstat!'
        from ./distkeys:200:in `commit'
        from ./distkeys:571:in `handle_host'
        from ./distkeys:677:in `block in handle_gwhost'
        from ./distkeys:660:in `each'
        from ./distkeys:660:in `handle_gwhost'
        from ./distkeys:692:in `loop'
        from ./distkeys:797:in `<main>'


I also tried after purging ruby-net-ssh which also removes ruby-net-sftp and
ruby-net-ssh-gateway and installing as gems:

mango:~# gem install net-sftp net-ssh net-ssh-gateway
Fetching: net-ssh-2.6.7.gem (100%)
Fetching: net-sftp-2.1.2.gem (100%)
Successfully installed net-ssh-2.6.7
Successfully installed net-sftp-2.1.2
Successfully installed net-ssh-2.6.7


This gives the following backtrace:

/var/lib/gems/1.9.1/gems/net-ssh-2.6.7/lib/net/ssh/connection/session.rb:299:in 
`[]=': can't add a new key into hash during iteration (RuntimeError)
        from 
/var/lib/gems/1.9.1/gems/net-ssh-2.6.7/lib/net/ssh/connection/session.rb:299:in 
`open_channel'
        from 
/var/lib/gems/1.9.1/gems/net-ssh-2.6.7/lib/net/ssh/connection/session.rb:323:in 
`exec'
        from 
/var/lib/gems/1.9.1/gems/net-ssh-2.6.7/lib/net/ssh/connection/session.rb:357:in 
`exec!'
        from ./distkeys:206:in `block in commit'
        from 
/var/lib/gems/1.9.1/gems/net-sftp-2.1.2/lib/net/sftp/request.rb:87:in `call'
        from 
/var/lib/gems/1.9.1/gems/net-sftp-2.1.2/lib/net/sftp/request.rb:87:in 
`respond_to'
        from 
/var/lib/gems/1.9.1/gems/net-sftp-2.1.2/lib/net/sftp/session.rb:948:in 
`dispatch_request'
        from 
/var/lib/gems/1.9.1/gems/net-sftp-2.1.2/lib/net/sftp/session.rb:911:in 
`when_channel_polled'
        from 
/var/lib/gems/1.9.1/gems/net-ssh-2.6.7/lib/net/ssh/connection/channel.rb:311:in 
`call'
        from 
/var/lib/gems/1.9.1/gems/net-ssh-2.6.7/lib/net/ssh/connection/channel.rb:311:in 
`process'
        from 
/var/lib/gems/1.9.1/gems/net-ssh-2.6.7/lib/net/ssh/connection/session.rb:217:in 
`block in preprocess'
        from 
/var/lib/gems/1.9.1/gems/net-ssh-2.6.7/lib/net/ssh/connection/session.rb:217:in 
`each'
        from 
/var/lib/gems/1.9.1/gems/net-ssh-2.6.7/lib/net/ssh/connection/session.rb:217:in 
`preprocess'
        from 
/var/lib/gems/1.9.1/gems/net-ssh-2.6.7/lib/net/ssh/connection/session.rb:200:in 
`process'
        from 
/var/lib/gems/1.9.1/gems/net-ssh-2.6.7/lib/net/ssh/connection/session.rb:164:in 
`block in loop'
        from 
/var/lib/gems/1.9.1/gems/net-ssh-2.6.7/lib/net/ssh/connection/session.rb:164:in 
`loop'
        from 
/var/lib/gems/1.9.1/gems/net-ssh-2.6.7/lib/net/ssh/connection/session.rb:164:in 
`loop'
        from 
/var/lib/gems/1.9.1/gems/net-sftp-2.1.2/lib/net/sftp/session.rb:802:in `loop'
        from 
/var/lib/gems/1.9.1/gems/net-sftp-2.1.2/lib/net/sftp/request.rb:72:in `wait'
        from 
/var/lib/gems/1.9.1/gems/net-sftp-2.1.2/lib/net/sftp/session.rb:842:in 
`wait_for'
        from 
/var/lib/gems/1.9.1/gems/net-sftp-2.1.2/lib/net/sftp/session.rb:320:in `lstat!'
        from ./distkeys:200:in `commit'
        from ./distkeys:571:in `handle_host'
        from ./distkeys:677:in `block in handle_gwhost'
        from ./distkeys:660:in `each'
        from ./distkeys:660:in `handle_gwhost'
        from ./distkeys:692:in `loop'
        from ./distkeys:797:in `<main>'

With Ruby 1.8 this works.


The code where this happens in distkeys as of commit
bf13f12e8ca3846998cc1cb610403ad958979377 (I will add a tag
with this bug report number) to the git repo:


                request = @sftp.lstat!(newauthkeyfile) do | response |
                        if response.ok?
                                # File size okay?
                                if response[:attrs].size >= wantedsize
                                        puts "File does exist and has correct 
size, moving to #{@authkeyfile}..."
                                        # Move the new keyfile over the old one
                                        @ssh.exec!(  "mv  #{newauthkeyfile} 
#{@authkeyfile}" )

                                        # We saved the changes, so no unsaved 
changes anymore
                                        @changed = false
                                end
                        end
                end
                #@sftp.loop


URL to git repo is:

git://oss.teamix.org/distkeys.git


I am trying to work-around this issue by using sftp.rename now. I think its
a better choice than executing the mv command.

Unless there is some programming mistake in distkeys that Ruby 1.9 brings
to light I bet this is an upstream bug.

I am willing to forward / report upstream as well, but first wanted to have
this tracked in Debian BTS.


ms@mango:~> apt-show-versions | grep ruby-net
ruby-net-sftp/wheezy uptodate 1:2.0.5-3
ruby-net-ssh/wheezy uptodate 1:2.5.2-2
ruby-net-ssh-gateway/wheezy uptodate 1.1.0-2

Thanks,
Martin

-- System Information:
Debian Release: 7.1
  APT prefers stable
  APT policy: (500, 'stable'), (350, 'unstable'), (110, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.9-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages ruby-net-ssh depends on:
ii  ruby                          1:1.9.3
ii  ruby1.8 [ruby-interpreter]    1.8.7.358-7
ii  ruby1.9.1 [ruby-interpreter]  1.9.3.194-8.1

ruby-net-ssh recommends no packages.

ruby-net-ssh suggests no packages.

-- no debconf information

--- End Message ---
--- Begin Message ---
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 <[email protected]>:
> > > 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

--- End Message ---

Reply via email to