mirror of
https://github.com/danbulant/cushy
synced 2026-06-15 12:31:11 +00:00
Fixed a possible deadlock in block_until_updated
The animation doctest randomly failed on me this morning, and I isolated it to the order of the two mutexes. There's no reason to hold the deadlock mutex for more than the check for deadlock, so I switched which mutex the condvar is synchronizing using to ensure that another thread couldn't cause a deadlock by dropping a DynamicMutexGuard while the block_until_updated thread is performing its state check.
This commit is contained in:
parent
be483a92bd
commit
e4dfd9320d
1 changed files with 6 additions and 5 deletions
11
src/value.rs
11
src/value.rs
|
|
@ -1594,16 +1594,18 @@ impl<T> DynamicReader<T> {
|
|||
/// This function panics if this value is already locked by the current
|
||||
/// thread.
|
||||
pub fn block_until_updated(&mut self) -> bool {
|
||||
let mut deadlock_state = self.source.during_callback_state.lock().ignore_poison();
|
||||
assert!(
|
||||
deadlock_state
|
||||
self.source
|
||||
.during_callback_state
|
||||
.lock()
|
||||
.ignore_poison()
|
||||
.as_ref()
|
||||
.map_or(true, |state| state.locked_thread
|
||||
!= std::thread::current().id()),
|
||||
"deadlocked"
|
||||
);
|
||||
let mut state = self.source.state.lock().ignore_poison();
|
||||
loop {
|
||||
let state = self.source.state.lock().ignore_poison();
|
||||
if state.wrapped.generation != self.read_generation {
|
||||
return true;
|
||||
} else if state.readers == Arc::strong_count(&self.source)
|
||||
|
|
@ -1611,10 +1613,9 @@ impl<T> DynamicReader<T> {
|
|||
{
|
||||
return false;
|
||||
}
|
||||
drop(state);
|
||||
|
||||
// Wait for a notification of a change, which is synch
|
||||
deadlock_state = self.source.sync.wait(deadlock_state).ignore_poison();
|
||||
state = self.source.sync.wait(state).ignore_poison();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue