Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MultiProgress:insert_{after, before}: grab pb index immediately to av…
…oid deadlock with Ticker (#424) Before this change it is possible for a combination of Ticker and MultiProgress to deadlock due a lock inversion. Consider this code: let mp = MultiProgress::new(); let s = mp.add(ProgressBar::new_spinner()); s.enable_steady_tick(Duration::from_millis(50)); let p0 = mp.insert_after(&s, ProgressBar::new(10)); Inside `Ticker`, a lock on `BarState` is acquired and then the state is drawn to the draw target via `BarState::draw()`. `draw` calls `self.draw_target.width()` which in the case of `MultiProgress` locks `MultiState`. Meanwhile, the call to `insert_after` calls `MultiProgress::internalize` which locks the `MultiState`. Then `MultiState::insert` (in the case of `insert_after` and `insert_before`) locks the `BarState` in order to read the index. So we have thread 1 locking in this order: `BarState`, `MultiState` and thread 2 locking in this order: `MultiState`, `BarState` == boom The fix is to change `insert_after` and `insert_before` to immediately grab the index of the progress bar rather than deferring it to be done when the `MultiState` is already locked. This makes the locking order of thread 2 the same as that of 1.
- Loading branch information