mattbrictson/airbrussh

Handle @position=nil case properly

kenn opened this issue · 7 comments

kenn commented

During execution of a Capistrano task, I'm seeing the following error from time to time. It looks like @position can be nil in Airbrussh::CommandFormatter.

NoMethodError: undefined method `+' for nil:NilClass
.rvm/gems/ruby-2.3.0/gems/airbrussh-1.0.1/lib/airbrussh/command_formatter.rb:75:in `number'
.rvm/gems/ruby-2.3.0/gems/airbrussh-1.0.1/lib/airbrussh/command_formatter.rb:79:in `success_message'
.rvm/gems/ruby-2.3.0/gems/airbrussh-1.0.1/lib/airbrussh/command_formatter.rb:53:in `exit_message'
.rvm/gems/ruby-2.3.0/gems/airbrussh-1.0.1/lib/airbrussh/console_formatter.rb:49:in `log_command_exit'
.rvm/gems/ruby-2.3.0/gems/airbrussh-1.0.1/lib/airbrussh/delegating_formatter.rb:25:in `public_send'
.rvm/gems/ruby-2.3.0/gems/airbrussh-1.0.1/lib/airbrussh/delegating_formatter.rb:25:in `block (3 levels) in <class:DelegatingFormatter>'
.rvm/gems/ruby-2.3.0/gems/airbrussh-1.0.1/lib/airbrussh/delegating_formatter.rb:25:in `map'
.rvm/gems/ruby-2.3.0/gems/airbrussh-1.0.1/lib/airbrussh/delegating_formatter.rb:25:in `block (2 levels) in <class:DelegatingFormatter>'
.rvm/gems/ruby-2.3.0/gems/sshkit-1.10.0/lib/sshkit/backends/netssh.rb:137:in `execute_command'
.rvm/gems/ruby-2.3.0/gems/sshkit-1.10.0/lib/sshkit/backends/abstract.rb:137:in `block in create_command_and_execute'
.rvm/gems/ruby-2.3.0/gems/sshkit-1.10.0/lib/sshkit/backends/abstract.rb:137:in `tap'
.rvm/gems/ruby-2.3.0/gems/sshkit-1.10.0/lib/sshkit/backends/abstract.rb:137:in `create_command_and_execute'
.rvm/gems/ruby-2.3.0/gems/sshkit-1.10.0/lib/sshkit/backends/abstract.rb:69:in `execute'
config/deploy.rb:93:in `block (3 levels) in <top (required)>'
.rvm/gems/ruby-2.3.0/gems/sshkit-1.10.0/lib/sshkit/backends/abstract.rb:29:in `instance_exec'
.rvm/gems/ruby-2.3.0/gems/sshkit-1.10.0/lib/sshkit/backends/abstract.rb:29:in `run'
.rvm/gems/ruby-2.3.0/gems/sshkit-1.10.0/lib/sshkit/runners/parallel.rb:12:in `block (2 levels) in execute'

Thanks for the report! What versions of Capistrano and SSHKit are you running?

Also, if you could offer any insight into why this may be happening, I would appreciate the troubleshooting assistance. The @position value should never be nil, but maybe we can figure out the combination of circumstances that leads to the bug.

Some ideas:

  1. Are you deploying to multiple servers? It could be a threading issue.
  2. Are you mutating the SSHKit Command object as it is running?
  3. Do you encounter the bug always in the same step in your deploy, or is it unpredictable?

Worst case, I can patch the code so that nil is gracefully handled, rather than blow up with an exception. However we should still try to get the root cause if we can.

Thanks!

kenn commented

sshkit-1.10.0 / capistrano-3.5.0

Are you deploying to multiple servers? It could be a threading issue.

I vaguely remember that it occurred when I was deploying to multiple servers without host filters. So, yes.

Are you mutating the SSHKit Command object as it is running?

No.

Do you encounter the bug always in the same step in your deploy, or is it unpredictable?

It was pretty random, so it may be a threading issue as you mentioned. I'll use host filter to work around that for now.

As much as I wanted to help you more, I don't have time to dig into the source at this moment. Maybe I was too adventurous when I decided to upgrade Capistrano as well as Debian, Sunzi, MySQL, etc. at the same time... 😄

One more question: are you using invoke within an on block anywhere in your tasks? Like this:

on ... do
  execute ...
  execute ...
  invoke "some:task"
end
kenn commented

Yes, exactly.

Great. Now I think I understand how nested invoke plus multiple servers could trigger this bug. Thanks for the help!

Fix has been released in 1.0.2 🚢