Course contentsShow
← Rust
Lesson 859 of 1,9107. Error Handling PatternsFree lesson

Handling Poisoned Mutexes

Implement recovery strategies for shared state synchronization failures.

In this lesson, you will learn how to detect and recover from "poisoned" mutexes, a unique scenario where shared state becomes unreliable due to a panic.

What is a Poisoned Mutex?

In Rust, a Mutex becomes "poisoned" if a thread panics while holding the lock. Because the data inside the Mutex might have been left in an inconsistent or partially modified state, Rust prevents you from accidentally using that corrupted data. When you call .lock() on a poisoned mutex, it returns an Err(PoisonError).

Strategy: Recovery via into_inner()

If you know your application logic can safely continue despite the panic, or if you simply need to reset the state to a known good value, you can recover the lock. The PoisonError type provides an into_inner() method that allows you to access the underlying data despite the poisoning.

use std::sync::{Mutex, Arc};

let mutex = Arc::new(Mutex::new(0));

// Simulate a panic while holding the lock
let m = mutex.clone();
let _ = std::thread::spawn(move || {
    let mut data = m.lock().unwrap();
    *data += 1;
    panic!("Something went wrong!"); // Mutex becomes poisoned here
}).join();

// Attempt to acquire the lock again
match mutex.lock() {
    Ok(mut guard) => *guard += 1,
    Err(poisoned) => {
        // Recovery strategy: ignore the poison and get the data
        let mut guard = poisoned.into_inner();
        *guard = 0; // Reset state to a safe value
        println!("Recovered from poison! Data reset to 0.");
    }
}

When to Recover

Recovery should be handled with caution. Only call into_inner() if you are certain that the "corrupted" state does not violate your application's safety invariants. If the data is truly critical, it is often better to let the application terminate or restart that specific component rather than proceeding with invalid data.

Key Takeaway: When a Mutex is poisoned, you can either propagate the error to halt operations or explicitly recover the data using into_inner() to reset the state to a consistent value.