@@ -35,8 +35,20 @@ use crate::sys::sync as sys;
35
35
///
36
36
/// In addition, the panic detection is not ideal, so even unpoisoned mutexes
37
37
/// 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:
40
52
///
41
53
/// ```rust
42
54
/// use std::sync::Mutex;
@@ -58,8 +70,8 @@ use crate::sys::sync as sys;
58
70
/// // panics, `*ptr` keeps pointing at a dropped value. The intention
59
71
/// // is that this will poison the mutex, so the following calls to
60
72
/// // `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.
63
75
/// unsafe {
64
76
/// (*ptr).write(f((*ptr).read()));
65
77
/// }
@@ -73,6 +85,9 @@ use crate::sys::sync as sys;
73
85
/// [`unwrap()`]: Result::unwrap
74
86
/// [`PoisonError`]: super::PoisonError
75
87
/// [`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
76
91
///
77
92
/// # Examples
78
93
///
0 commit comments