logoalt Hacker News

kouteiheikayesterday at 5:51 PM4 repliesview on HN

> Poisoning: Panic Safety in Mutexes

This is one of the biggest design flaws in Rust's std, in my opinion.

Poisoning mutexes can have its use, but it's very rare in practice. Usually it's a huge misfeature that only introduces problems. More often than not panicking in a critical section is fine[1], but on the other hand poisoning a Mutex is a very convenient avenue for a denial-of-service attack, since a poisoned Mutex will just completely brick a given critical section.

I'm not saying such a project doesn't exist, but I don't think I've ever seen a project which does anything sensible with Mutex's `Poisoned` error besides ignoring it. It's always either an `unwrap` (and we know how well that can go [2]), or do the sensible thing and do this ridiculous song-and-dance:

    let guard = match mutex {
        Ok(guard) => guard,
        Err(poisoned) => poisoned.into_inner()
    };
Suffice to say, it's a pain.

So in a lot of projects when I need a mutex I just add `parking_lot`, because its performance is stellar, and it doesn't have the poisoning insanity to deal with.

[1] -- obviously it depends on a case-by-case basis, but if you're using such a low level primitive you should know what you're doing

[2] -- https://blog.cloudflare.com/18-november-2025-outage/#memory-...


Replies

LegionMammal978yesterday at 6:35 PM

> It's always either an `unwrap` (and we know how well that can go [2])

If a mutex has been poisoned, then something must have already panicked, likely in some other thread, so you're already in trouble at that point. It's fine to panic in a critical section if something's horribly wrong, the problem comes with blindly continuing after a panic in other threads that operate on the same data. In general, you're unlikely to know what that panic was, so you have no clue if the shared data might be incompletely modified or otherwise logically corrupted.

In general, unless I were being careful to maintain fault boundaries between threads or tasks (the archetypical example being an HTTP server handling independent requests), I'd want a panic in one thread to cascade into stopping the program as soon as possible. I wouldn't want to swallow it up and keep using the same data like nothing's wrong.

show 2 replies
sunshowersyesterday at 6:47 PM

To the contrary, the projects I've been part of have had no end of issues related to being cancelled in the middle of a critical section [1]. I consider poisoning to be table stakes for a mutex.

[1] https://sunshowers.io/posts/cancelling-async-rust/#the-pain-...

show 1 reply
JoshTriplettyesterday at 7:24 PM

We're currently working on separating poison from mutexes, such that the default mutexes won't have poisoning (no more `.lock().unwrap()`), and if you want poisoning you can use something like `Mutex<Poison<T>>`.

show 2 replies
thayneyesterday at 6:19 PM

There are cases where it is useful.

I had a case where if the mutex was poisened it was possible to reset the lock to a safe state (by writing a new value to the locked content).

Or you may want to drop some resource or restart some operation instead of panicing if it is poisoned.

But I agree that the default behavior should be that the user doesn't have to worry about it.