Mutex::lock returns Err(PoisonError) after a panic in std::sync — recover or propagate?
20.5K reputation · 01 Nov 2024, 11:38 UTC
My Rust service shares state behind a std::sync::Mutex. After a worker thread panicked while holding the lock, every subsequent lock() call from other threads returns Err(PoisonError), which is the documented failure condition for a poisoned mutex.
The standard library documents two paths: propagate by unwrapping (turning the poison into another panic), or recover via PoisonError::into_inner() / Mutex::clear_poison and continue using the guard. What I cannot find is any documented criterion for deciding which is correct. The poisoning mechanism exists because the guarded data may have been left mid-update, but the type system cannot tell me whether my invariants are actually broken.
My guarded state is a cache plus counters; a panic mid-update could leave counters inconsistent with the cache, but the data is reconstructible. I am on a recent stable toolchain, so clear_poison should be available, though I have not confirmed the exact stabilization version.
Is there an accepted rule for when recovery via into_inner() is sound versus when propagation is the only safe choice? Does the answer change if I can re-validate the invariants before reusing the guard? And does clear_poison carry any semantic difference from unwrapping the PoisonError directly?