mirror of
https://github.com/danbulant/cushy
synced 2026-06-19 22:41:10 +00:00
Fixed deadlock with DynamicMutexGuard::unlocked
During the change callback process, unlocked is called to allow the change callbacks to run while the dynamic is unlocked. The error with the previous version of this code is that the during_callback_state was always overwritten when being returned. The problem is that another thread could currently have the mutex locked and could have stored its own state -- which can happen if two threads are both trying to invoke change callbacks at the same time. By moving the state saving and reloading to only happen when the mutex guard is acquired, we can ensure that interleaving threads will work correctly.
This commit is contained in:
parent
f61cb2b91b
commit
6a1f7f5462
2 changed files with 6 additions and 5 deletions
|
|
@ -21,6 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
window.
|
||||
- `CallbackHandle` now has a `must_use` hint that might help users discover the
|
||||
persist function.
|
||||
- Fixed a deadlock that could occur when multiple threads were attempting to
|
||||
execute change callbacks for the same dynamic at the same time.
|
||||
|
||||
### Added
|
||||
|
||||
|
|
|
|||
|
|
@ -1437,11 +1437,10 @@ where
|
|||
|
||||
impl<'a, T> DynamicMutexGuard<'a, T> {
|
||||
fn unlocked(&mut self, while_unlocked: impl FnOnce()) {
|
||||
MutexGuard::unlocked(&mut self.guard, || {
|
||||
let current_state = self.dynamic.during_callback_state.lock().take();
|
||||
while_unlocked();
|
||||
*self.dynamic.during_callback_state.lock() = current_state;
|
||||
});
|
||||
let previous_state = self.dynamic.during_callback_state.lock().take();
|
||||
MutexGuard::unlocked(&mut self.guard, while_unlocked);
|
||||
|
||||
*self.dynamic.during_callback_state.lock() = previous_state;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue