Skip to content

Commit

Permalink
fix deadlock
Browse files Browse the repository at this point in the history
Kudos to @Ekleog for finding it!
  • Loading branch information
matklad committed May 19, 2022
1 parent 0067580 commit 5386606
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 3 deletions.
7 changes: 4 additions & 3 deletions src/imp_pl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ struct Guard<'a> {
impl<'a> Drop for Guard<'a> {
fn drop(&mut self) {
self.state.store(self.new_state, Ordering::Release);
unsafe {
let key = self.state as *const _ as usize;
parking_lot_core::unpark_all(key, parking_lot_core::DEFAULT_UNPARK_TOKEN);
}
}
}

Expand All @@ -136,9 +140,6 @@ fn initialize_inner(state: &AtomicU8, init: &mut dyn FnMut() -> bool) {
if init() {
guard.new_state = COMPLETE;
}
unsafe {
parking_lot_core::unpark_all(key, parking_lot_core::DEFAULT_UNPARK_TOKEN);
}
return;
}
Err(COMPLETE) => return,
Expand Down
22 changes: 22 additions & 0 deletions tests/it.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,28 @@ mod sync {
assert_eq!(cell.get(), Some(&"hello".to_string()));
}

#[test]
#[cfg_attr(miri, ignore)] // miri doesn't support Barrier
fn get_or_init_stress() {
use std::sync::Barrier;
let n_threads = 1_000;
let n_cells = 1_000;
let cells: Vec<_> = std::iter::repeat_with(|| (Barrier::new(n_threads), OnceCell::new()))
.take(n_cells)
.collect();
scope(|s| {
for _ in 0..n_threads {
s.spawn(|_| {
for (i, (b, s)) in cells.iter().enumerate() {
b.wait();
let j = s.get_or_init(|| i);
assert_eq!(*j, i);
}
});
}
}).unwrap();
}

#[test]
fn from_impl() {
assert_eq!(OnceCell::from("value").get(), Some(&"value"));
Expand Down

0 comments on commit 5386606

Please sign in to comment.