Closed ghost closed 10 years ago
I never tried to run this from different threads, but I'm sure there's a better way to handle this. Do you have a simple test case that exhibits this behavior?
Try to run this several times in the console.
t = []
10.times { t << Thread.new { bar = ProgressBar.new(100, :bar, :percentage, :rate, :elapsed, :eta); 100.times { bar.increment!; sleep(0.01) } } }
t.each(&:join)
The result is this
NoMethodError: undefined method `-' for nil:NilClass
from /Users/sergeygoncharov/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/progress_bar-1.0.2/lib/progress_bar.rb:143:in `bar_width'
from /Users/sergeygoncharov/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/progress_bar-1.0.2/lib/progress_bar.rb:100:in `render_bar'
from /Users/sergeygoncharov/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/progress_bar-1.0.2/lib/progress_bar.rb:92:in `render'
from /Users/sergeygoncharov/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/progress_bar-1.0.2/lib/progress_bar.rb:77:in `block in to_s'
from /Users/sergeygoncharov/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/progress_bar-1.0.2/lib/progress_bar.rb:76:in `each'
from /Users/sergeygoncharov/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/progress_bar-1.0.2/lib/progress_bar.rb:76:in `inject'
from /Users/sergeygoncharov/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/progress_bar-1.0.2/lib/progress_bar.rb:76:in `to_s'
from /Users/sergeygoncharov/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/progress_bar-1.0.2/lib/progress_bar.rb:39:in `write'
from /Users/sergeygoncharov/.rbenv/versions/1.9.3-p448/lib/ruby/gems/1.9.1/gems/progress_bar-1.0.2/lib/progress_bar.rb:32:in `increment!'
from (irb):48:in `block (3 levels) in irb_binding'
from (irb):48:in `times'
from (irb):48:in `block (2 levels) in irb_binding'
I tried that several times in ruby 2.1.2, an grabbed rbx and rubinus to try it there, but am unable to reproduce it at all in irb.
I think the right way to do that is to wrap that ivar in a thread mutex, but I wish I could make it fail to verify that would fix it.
The code above indeed seems to work without any error. I played in the console with different examples before pasting the example and I missed one more required step to replicate it. Here is the full code that fails on both 1.9.3 and 2.1.2
bar = ProgressBar.new(100, :bar, :percentage, :rate, :elapsed, :eta)
t = []
10.times { t << Thread.new { 10.times { bar.increment!; sleep(0.01) } } }
t.each(&:join)
Thanks, I was able to reproduce it from that. I've released a 1.0.3 with the fix.
When running in multi-threaded environment, @terminal_width sometimes becomes nil.