console-rs / indicatif

A command line progress reporting library for Rust
MIT License
4.23k stars 240 forks source link

ticker_drop test fails occasionally - race condition in Ticker? #464

Closed chris-laplante closed 1 year ago

chris-laplante commented 1 year ago

The ticker_drop render test occasionally fails.

Reproduce it by running this command:

while cargo test --all-features ticker_drop; do :; done

It will eventually fail with something like this:

running 1 test
test ticker_drop ... FAILED

failures:

---- ticker_drop stdout ----
thread 'ticker_drop' panicked at 'assertion failed: `(left == right)`
  left: `"⠁ doing stuff 0\n  doing stuff 1\n  doing stuff 2\n  doing stuff 3\n  doing stuff 4"`,
 right: `"  doing stuff 0\n  doing stuff 1\n  doing stuff 2\n  doing stuff 3\n  doing stuff 4"`', tests/render.rs:347:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Somehow the spinner is not correctly getting finished. Clearly there is a subtle race condition somewhere but I haven't been able to track it down.

chris-laplante commented 1 year ago

This turned out to be a problem with MultiProgress, not Ticker.

To simplify the problem, you can change the number of tickers from 5 to 2. Depending on the order in which the tickers interleaved, you could end up with this:

Ticker 0 Ticker 1 MultiProgress
Tick, draw ⠁ doing stuff 0 Draw ⠁ doing stuff 0
Tick, draw ⠁ doing stuff 1 Draw \n⠁ doing stuff 1
Arc drops the BarState, so draw doing stuff 0 Ticker 0 Weak<BarState> is dead, so it's a zombie :zombie:. Erase 1 line, draw \n⠁ doing stuff 1

In summary, the Ticker and ProgressBar are working as they should, but the way MultiProgress detects zombies is broken wrt how "finish"ing works.