Skip to content

Commit 5b8c614

Browse files
committed
Add a list of failure conditions for poisoning
1 parent da4687b commit 5b8c614

File tree

1 file changed

+19
-4
lines changed

1 file changed

+19
-4
lines changed

library/std/src/sync/poison/mutex.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,20 @@ use crate::sys::sync as sys;
3535
///
3636
/// In addition, the panic detection is not ideal, so even unpoisoned mutexes
3737
/// need to be handled with care, since certain panics may have been skipped.
38-
/// Therefore, `unsafe` code cannot rely on poisoning for soundness. Here's an
39-
/// example of **incorrect** use of poisoning:
38+
/// Here is a non-exhaustive list of situations where this might occur:
39+
///
40+
/// - If a mutex is locked while a panic is underway, e.g. within a [`Drop`]
41+
/// implementation or a [panic hook], panicking for the second time while the
42+
/// lock is held will leave the mutex unpoisoned. Note that while double panic
43+
/// usually aborts the program, [`catch_unwind`] can prevent this.
44+
///
45+
/// - Locking and unlocking the mutex across different panic contexts, e.g. by
46+
/// storing the guard to a [`Cell`] within [`Drop::drop`] and accessing it
47+
/// outside, or vice versa, can affect poisoning status in an unexpected way.
48+
///
49+
/// While this rarely happens in realistic code, `unsafe` code cannot rely on
50+
/// poisoning for soundness, since the behavior of poisoning can depend on
51+
/// outside context. Here's an example of **incorrect** use of poisoning:
4052
///
4153
/// ```rust
4254
/// use std::sync::Mutex;
@@ -58,8 +70,8 @@ use crate::sys::sync as sys;
5870
/// // panics, `*ptr` keeps pointing at a dropped value. The intention
5971
/// // is that this will poison the mutex, so the following calls to
6072
/// // `replace_with` will panic without reading `*ptr`. But since
61-
/// // poisoning is not guaranteed to occur, this can lead to
62-
/// // use-after-free.
73+
/// // poisoning is not guaranteed to occur if this is run from a panic
74+
/// // hook, this can lead to use-after-free.
6375
/// unsafe {
6476
/// (*ptr).write(f((*ptr).read()));
6577
/// }
@@ -73,6 +85,9 @@ use crate::sys::sync as sys;
7385
/// [`unwrap()`]: Result::unwrap
7486
/// [`PoisonError`]: super::PoisonError
7587
/// [`into_inner`]: super::PoisonError::into_inner
88+
/// [panic hook]: crate::panic::set_hook
89+
/// [`catch_unwind`]: crate::panic::catch_unwind
90+
/// [`Cell`]: crate::cell::Cell
7691
///
7792
/// # Examples
7893
///

0 commit comments

Comments
 (0)