Skip to content

Commit e9e3a70

Browse files
committed
fix: recover locator cache in-flight poison (PR #419)
1 parent cad339d commit e9e3a70

1 file changed

Lines changed: 47 additions & 4 deletions

File tree

crates/pet-core/src/cache.rs

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,12 @@ impl<K: Eq + Hash, V> InFlightOwnerGuard<'_, K, V> {
6060
.entry
6161
.result
6262
.lock()
63-
.expect("locator cache in-flight result lock poisoned") = Some(result);
63+
.unwrap_or_else(|poisoned| poisoned.into_inner()) = Some(result);
6464

6565
if let Some(key) = self.key.take() {
6666
self.in_flight
6767
.lock()
68-
.expect("locator cache in-flight lock poisoned")
68+
.unwrap_or_else(|poisoned| poisoned.into_inner())
6969
.remove(&key);
7070
}
7171

@@ -212,12 +212,12 @@ impl<K: Eq + Hash, V: Clone> LocatorCache<K, V> {
212212
let mut result = entry
213213
.result
214214
.lock()
215-
.expect("locator cache in-flight result lock poisoned");
215+
.unwrap_or_else(|poisoned| poisoned.into_inner());
216216
while result.is_none() {
217217
result = entry
218218
.changed
219219
.wait(result)
220-
.expect("locator cache in-flight condvar poisoned");
220+
.unwrap_or_else(|poisoned| poisoned.into_inner());
221221
}
222222

223223
result.clone().unwrap()
@@ -414,6 +414,49 @@ mod tests {
414414
);
415415
}
416416

417+
#[test]
418+
fn test_cache_publish_result_recovers_poisoned_in_flight_locks() {
419+
let key = "key".to_string();
420+
let entry = Arc::new(InFlightEntry::new());
421+
let in_flight: Arc<Mutex<HashMap<String, Arc<InFlightEntry<i32>>>>> =
422+
Arc::new(Mutex::new(HashMap::new()));
423+
424+
in_flight.lock().unwrap().insert(key.clone(), entry.clone());
425+
426+
let poison_entry = entry.clone();
427+
assert!(thread::spawn(move || {
428+
let _guard = poison_entry.result.lock().unwrap();
429+
panic!("poison result lock");
430+
})
431+
.join()
432+
.is_err());
433+
434+
let poison_in_flight = in_flight.clone();
435+
assert!(thread::spawn(move || {
436+
let _guard = poison_in_flight.lock().unwrap();
437+
panic!("poison in-flight lock");
438+
})
439+
.join()
440+
.is_err());
441+
442+
let owner = InFlightOwnerGuard {
443+
key: Some(key),
444+
entry: entry.clone(),
445+
in_flight: &in_flight,
446+
};
447+
448+
owner.complete(Some(42));
449+
450+
assert_eq!(
451+
LocatorCache::<String, i32>::wait_for_in_flight(entry),
452+
Some(42)
453+
);
454+
assert!(in_flight
455+
.lock()
456+
.unwrap_or_else(|poisoned| poisoned.into_inner())
457+
.is_empty());
458+
}
459+
417460
#[test]
418461
fn test_cache_clear() {
419462
let cache: LocatorCache<String, i32> = LocatorCache::new();

0 commit comments

Comments
 (0)