File tree Expand file tree Collapse file tree 8 files changed +33
-2
lines changed Expand file tree Collapse file tree 8 files changed +33
-2
lines changed Original file line number Diff line number Diff line change @@ -27,6 +27,9 @@ unsafe impl<T> Sync for Lazy<T> {}
27
27
28
28
impl < T : Send + Sync + ' static > Lazy < T > {
29
29
pub const fn new ( init : fn ( ) -> Arc < T > ) -> Lazy < T > {
30
+ // `lock` is never initialized fully, so this mutex is reentrant!
31
+ // Do not use it in a way that might be reentrant, that could lead to
32
+ // aliasing `&mut`.
30
33
Lazy {
31
34
lock : Mutex :: new ( ) ,
32
35
ptr : Cell :: new ( ptr:: null_mut ( ) ) ,
@@ -48,6 +51,7 @@ impl<T: Send + Sync + 'static> Lazy<T> {
48
51
}
49
52
}
50
53
54
+ // Must only be called with `lock` held
51
55
unsafe fn init ( & ' static self ) -> Arc < T > {
52
56
// If we successfully register an at exit handler, then we cache the
53
57
// `Arc` allocation in our own internal box (it will get deallocated by
@@ -60,6 +64,9 @@ impl<T: Send + Sync + 'static> Lazy<T> {
60
64
} ;
61
65
drop ( Box :: from_raw ( ptr) )
62
66
} ) ;
67
+ // This could reentrantly call `init` again, which is a problem
68
+ // because our `lock` allows reentrancy!
69
+ // FIXME: Add argument why this is okay.
63
70
let ret = ( self . init ) ( ) ;
64
71
if registered. is_ok ( ) {
65
72
self . ptr . set ( Box :: into_raw ( Box :: new ( ret. clone ( ) ) ) ) ;
Original file line number Diff line number Diff line change @@ -80,6 +80,9 @@ mod imp {
80
80
81
81
static mut ARGC : isize = 0 ;
82
82
static mut ARGV : * const * const u8 = ptr:: null ( ) ;
83
+ // `ENV_LOCK` is never initialized fully, so this mutex is reentrant!
84
+ // Do not use it in a way that might be reentrant, that could lead to
85
+ // aliasing `&mut`.
83
86
static LOCK : Mutex = Mutex :: new ( ) ;
84
87
85
88
pub unsafe fn init ( argc : isize , argv : * const * const u8 ) {
Original file line number Diff line number Diff line change @@ -25,8 +25,10 @@ unsafe impl Sync for Mutex {}
25
25
#[ allow( dead_code) ] // sys isn't exported yet
26
26
impl Mutex {
27
27
pub const fn new ( ) -> Mutex {
28
- // Might be moved and address is changing it is better to avoid
29
- // initialization of potentially opaque OS data before it landed
28
+ // Might be moved to a different address, so it is better to avoid
29
+ // initialization of potentially opaque OS data before it landed.
30
+ // Be very careful using this newly constructed `Mutex`, it should
31
+ // be initialized by calling `init()` first!
30
32
Mutex { inner : UnsafeCell :: new ( libc:: PTHREAD_MUTEX_INITIALIZER ) }
31
33
}
32
34
#[ inline]
Original file line number Diff line number Diff line change @@ -33,6 +33,9 @@ use sys::fd;
33
33
use vec;
34
34
35
35
const TMPBUF_SZ : usize = 128 ;
36
+ // `ENV_LOCK` is never initialized fully, so this mutex is reentrant!
37
+ // Do not use it in a way that might be reentrant, that could lead to
38
+ // aliasing `&mut`.
36
39
static ENV_LOCK : Mutex = Mutex :: new ( ) ;
37
40
38
41
Original file line number Diff line number Diff line change @@ -23,6 +23,9 @@ type Queue = Vec<Box<dyn FnBox()>>;
23
23
// on poisoning and this module needs to operate at a lower level than requiring
24
24
// the thread infrastructure to be in place (useful on the borders of
25
25
// initialization/destruction).
26
+ // `LOCK` is never initialized fully, so this mutex is reentrant!
27
+ // Do not use it in a way that might be reentrant, that could lead to
28
+ // aliasing `&mut`.
26
29
static LOCK : Mutex = Mutex :: new ( ) ;
27
30
static mut QUEUE : * mut Queue = ptr:: null_mut ( ) ;
28
31
@@ -72,6 +75,9 @@ pub fn push(f: Box<dyn FnBox()>) -> bool {
72
75
unsafe {
73
76
let _guard = LOCK . lock ( ) ;
74
77
if init ( ) {
78
+ // This could reentrantly call `push` again, which is a problem because
79
+ // `LOCK` allows reentrancy!
80
+ // FIXME: Add argument why this is okay.
75
81
( * QUEUE ) . push ( f) ;
76
82
true
77
83
} else {
Original file line number Diff line number Diff line change @@ -24,11 +24,15 @@ impl Mutex {
24
24
///
25
25
/// Behavior is undefined if the mutex is moved after it is
26
26
/// first used with any of the functions below.
27
+ /// Also, the mutex might not be fully functional without calling
28
+ /// `init`! For example, on unix, the mutex is reentrant
29
+ /// until `init` reconfigures it appropriately.
27
30
pub const fn new ( ) -> Mutex { Mutex ( imp:: Mutex :: new ( ) ) }
28
31
29
32
/// Prepare the mutex for use.
30
33
///
31
34
/// This should be called once the mutex is at a stable memory address.
35
+ /// It must not be called concurrently with any other operation.
32
36
#[ inline]
33
37
pub unsafe fn init ( & mut self ) { self . 0 . init ( ) }
34
38
Original file line number Diff line number Diff line change @@ -161,6 +161,9 @@ impl StaticKey {
161
161
// Additionally a 0-index of a tls key hasn't been seen on windows, so
162
162
// we just simplify the whole branch.
163
163
if imp:: requires_synchronized_create ( ) {
164
+ // `INIT_LOCK` is never initialized fully, so this mutex is reentrant!
165
+ // Do not use it in a way that might be reentrant, that could lead to
166
+ // aliasing `&mut`.
164
167
static INIT_LOCK : Mutex = Mutex :: new ( ) ;
165
168
let _guard = INIT_LOCK . lock ( ) ;
166
169
let mut key = self . key . load ( Ordering :: SeqCst ) ;
Original file line number Diff line number Diff line change @@ -940,6 +940,9 @@ pub struct ThreadId(u64);
940
940
impl ThreadId {
941
941
// Generate a new unique thread ID.
942
942
fn new ( ) -> ThreadId {
943
+ // `GUARD` is never initialized fully, so this mutex is reentrant!
944
+ // Do not use it in a way that might be reentrant, that could lead to
945
+ // aliasing `&mut`.
943
946
static GUARD : mutex:: Mutex = mutex:: Mutex :: new ( ) ;
944
947
static mut COUNTER : u64 = 0 ;
945
948
You can’t perform that action at this time.
0 commit comments