paul / progress_bar

A Ruby terminal progress_bar
Do What The F*ck You Want To Public License
623 stars 49 forks source link

Bar duplicates/recreates itself at random intervals #40

Closed Gabriel-Bowater closed 6 years ago

Gabriel-Bowater commented 6 years ago

Hi, I've just had a go at using this bar to replace a bunch of terminal spam in a program I use for batching and compare graph sets. It works great, love the various metrics you can include, but I've come a cross a couple of issues. First one - While it's running it will usually but not always sort of jump the groove and create a new version of the bar graph and other metrics, keeping the progress, but leaving the partially filled version behind. It will do this multiple times on longer operations, but not at a consistent interval. Terminal screen cap attached.
progress_bar_1

How I'm using it to cause the above :

                progress_bar = ProgressBar.new(images.length, :bar,:elapsed,:counter)
        done = false
        while images.length > 0
            image = images.pop
            total_count -=1
            Signal.trap("CLD") { counter += 1; progress_bar.increment! if !done}
            Process.wait if counter <= 0
            counter -= 1
            puts "#{total_count} images remaining" if !@quiet
            fork do
                if File.exist?("#{sets[0]}#{image}") && File.exist?("#{sets[1]}#{image}")
                    return_ratio = compare_image_pair(["#{sets[0]}#{image}","#{sets[1]}#{image}"])
                    out_file.puts "#{image}:#{return_ratio}"
                else
                    puts "#{sets[0]}#{image}"
                    puts "#{sets[1]}#{image}"
                    puts "Unmatched file #{image}"
                end
                exit(0)
            end
        end
        Process.waitall
        puts "\nCompleted in #{Time.now - start_time} seconds with #{@max_processes} subprocesses"
        Process.waitall
        done = true
        progress_bar = nil 
Gabriel-Bowater commented 6 years ago

My problem, needed to make the .increment! call in Mutex handler, like:

mutex = Mutex.new
[...]
mutex.synchronize{progress_bar.increment!}

https://ruby-doc.org/core-2.2.0/Mutex.html for posterity

paul commented 6 years ago

Ah, yeah, while ProgresBar itself is threadsafe, having more than one bar at a time write to the console is not. I'm a little surprised that it split it in half, rather than both bars just clobbering each others' output though.