diff --git a/src/value.rs b/src/value.rs index 11d9102..515d218 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1227,7 +1227,7 @@ impl Dynamic { } fn lock_inner(&self) -> DynamicGuard<'_, T, READONLY> { - let guard = self.0.state().expect("deadlocked"); + let mut guard = self.0.state().expect("deadlocked"); // Before allowing a lock, we need to ensure that the current change // callbacks aren't executing. Otherwise, during drop of this guard, if // we notify of changes from a second thread than one set is already @@ -1235,16 +1235,19 @@ impl Dynamic { // other and deadlocking. By ensuring a single guard and change // callbacks cycle can exist at any one time, we prevent this deadlock. if !READONLY && guard.callbacks.currently_executing.lock().thread.is_some() { - let current_thread_id = std::thread::current().id(); let callbacks = guard.callbacks.clone(); - let mut executing = callbacks.currently_executing.lock(); - loop { - match &executing.thread { - Some(th) if th == ¤t_thread_id => panic!("deadlocked"), - Some(_) => callbacks.sync.wait(&mut executing), - None => break, - }; - } + guard.unlocked(|| { + let current_thread_id = std::thread::current().id(); + let mut executing = callbacks.currently_executing.lock(); + + loop { + match &executing.thread { + Some(th) if th == ¤t_thread_id => break, + None => break, + Some(_) => callbacks.sync.wait(&mut executing), + }; + } + }); } DynamicGuard { guard: DynamicOrOwnedGuard::Dynamic(guard),