[DRE-maint] Bug#714606: help with fixing ruby-net-ssh: can't add a new key into hash during iteration during ssh.exec
Martin Steigerwald
ms at teamix.de
Tue Apr 14 11:00:19 UTC 2015
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.
>
>
> Hi!
>
> I seek help with fixing
>
> https://bugs.debian.org/714606
>
> aka
>
> https://github.com/net-ssh/net-ssh/issues/110
>
>
> The error message on trying ssh.exec is:
>
> /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:305:in `open_channel': can't add a new key into hash during iteration (RuntimeError)
>
>
> Here is the offending source:
>
> https://github.com/net-ssh/net-ssh/blob/master/lib/net/ssh/connection/session.rb#L306
>
>
> As far as I get the error is due to method exed in same file using
>
> open_channel do |channel|
>
> which then puts the assignment
>
> channels[local_id] = channel
>
> in open_channel into an iteration.
>
> But I asked on #ruby-de and the do / end there is a block, not an iteration.
>
> However in the backtrace there is
>
> /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:305:in `open_channel': can't add a new key into hash during iteration (RuntimeError)
> from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:329:in `exec'
> from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:363:in `exec!'
> from /homelokal/ms/Debian/distkeys/distkeys.git/distkeys:174:in `block in commit'
> from /usr/lib/ruby/vendor_ruby/net/sftp/request.rb:87:in `call'
> from /usr/lib/ruby/vendor_ruby/net/sftp/request.rb:87:in `respond_to'
> from /usr/lib/ruby/vendor_ruby/net/sftp/session.rb:948:in `dispatch_request'
> from /usr/lib/ruby/vendor_ruby/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:222:in `block in preprocess'
> from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:222:in `each'
> from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:222:in `preprocess'
> from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:205:in `process'
> from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:169:in `block in loop'
> from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:169:in `loop'
> from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:169:in `loop'
> from /usr/lib/ruby/vendor_ruby/net/ssh/connection/channel.rb:269:in `wait'
> from /usr/lib/ruby/vendor_ruby/net/ssh/connection/session.rb:364:in `exec!'
> from /homelokal/ms/Debian/distkeys/distkeys.git/distkeys:184:in `commit'
> from /homelokal/ms/Debian/distkeys/distkeys.git/distkeys:628:in `handle_host'
> from /homelokal/ms/Debian/distkeys/distkeys.git/distkeys:703:in `block in handle_gwhost'
> from /homelokal/ms/Debian/distkeys/distkeys.git/distkeys:686:in `each'
> from /homelokal/ms/Debian/distkeys/distkeys.git/distkeys:686:in `handle_gwhost'
> from /homelokal/ms/Debian/distkeys/distkeys.git/distkeys:718:in `loop'
> from /homelokal/ms/Debian/distkeys/distkeys.git/distkeys:828:in `<main>'
>
> 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
>
>
>
> Do you see a way to fix this up without changing the semantics of open_channel?
Okay, I now got further help from #ruby-de and there is a fix I can do inside distkeys:
ok=false
@sftp.lstat( ".ssh" ) do |response| ok = response.ok?; end
if not ok then
puts "~/.ssh does not seem to exist, creating it with 700..."
@ssh.exec!( "mkdir ~/.ssh" )
@ssh.exec!( "chmod 700 ~/.ssh" )
end
i.e. first finish sftp then to the ssh exec stuff.
Pushed:
https://github.com/teamix/distkeys/commit/1092384f54d6531ce1106c4fe7b2f6833a2bba5b
I can now fix all other occurences of this in my script.
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.
Thanks,
--
Martin Steigerwald | Consultant / Trainer
teamix GmbH
Südwestpark 43
90449 Nürnberg
Tel.: +49 911 30999 55 | Fax: +49 911 30999 99
mail: martin.steigerwald at teamix.de | web: http://www.teamix.de | blog: http://blog.teamix.de
Amtsgericht Nürnberg, HRB 18320 | Geschäftsführer: Oliver Kügow, Richard Müller
** Data Management Day | 29.04.2015 bei teamix **
Jetzt anmelden unter www.teamix.de/CommVault
More information about the Pkg-ruby-extras-maintainers
mailing list