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> {}
2727
2828impl < T : Send + Sync + ' static > Lazy < T > {
2929 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`.
3033 Lazy {
3134 lock : Mutex :: new ( ) ,
3235 ptr : Cell :: new ( ptr:: null_mut ( ) ) ,
@@ -48,6 +51,7 @@ impl<T: Send + Sync + 'static> Lazy<T> {
4851 }
4952 }
5053
54+ // Must only be called with `lock` held
5155 unsafe fn init ( & ' static self ) -> Arc < T > {
5256 // If we successfully register an at exit handler, then we cache the
5357 // `Arc` allocation in our own internal box (it will get deallocated by
@@ -60,6 +64,9 @@ impl<T: Send + Sync + 'static> Lazy<T> {
6064 } ;
6165 drop ( Box :: from_raw ( ptr) )
6266 } ) ;
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.
6370 let ret = ( self . init ) ( ) ;
6471 if registered. is_ok ( ) {
6572 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 {
8080
8181 static mut ARGC : isize = 0 ;
8282 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`.
8386 static LOCK : Mutex = Mutex :: new ( ) ;
8487
8588 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 {}
2525#[ allow( dead_code) ] // sys isn't exported yet
2626impl Mutex {
2727 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!
3032 Mutex { inner : UnsafeCell :: new ( libc:: PTHREAD_MUTEX_INITIALIZER ) }
3133 }
3234 #[ inline]
Original file line number Diff line number Diff line change @@ -33,6 +33,9 @@ use sys::fd;
3333use vec;
3434
3535const 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`.
3639static ENV_LOCK : Mutex = Mutex :: new ( ) ;
3740
3841
Original file line number Diff line number Diff line change @@ -23,6 +23,9 @@ type Queue = Vec<Box<dyn FnBox()>>;
2323// on poisoning and this module needs to operate at a lower level than requiring
2424// the thread infrastructure to be in place (useful on the borders of
2525// 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`.
2629static LOCK : Mutex = Mutex :: new ( ) ;
2730static mut QUEUE : * mut Queue = ptr:: null_mut ( ) ;
2831
@@ -72,6 +75,9 @@ pub fn push(f: Box<dyn FnBox()>) -> bool {
7275 unsafe {
7376 let _guard = LOCK . lock ( ) ;
7477 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.
7581 ( * QUEUE ) . push ( f) ;
7682 true
7783 } else {
Original file line number Diff line number Diff line change @@ -24,11 +24,15 @@ impl Mutex {
2424 ///
2525 /// Behavior is undefined if the mutex is moved after it is
2626 /// 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.
2730 pub const fn new ( ) -> Mutex { Mutex ( imp:: Mutex :: new ( ) ) }
2831
2932 /// Prepare the mutex for use.
3033 ///
3134 /// This should be called once the mutex is at a stable memory address.
35+ /// It must not be called concurrently with any other operation.
3236 #[ inline]
3337 pub unsafe fn init ( & mut self ) { self . 0 . init ( ) }
3438
Original file line number Diff line number Diff line change @@ -161,6 +161,9 @@ impl StaticKey {
161161 // Additionally a 0-index of a tls key hasn't been seen on windows, so
162162 // we just simplify the whole branch.
163163 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`.
164167 static INIT_LOCK : Mutex = Mutex :: new ( ) ;
165168 let _guard = INIT_LOCK . lock ( ) ;
166169 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);
940940impl ThreadId {
941941 // Generate a new unique thread ID.
942942 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`.
943946 static GUARD : mutex:: Mutex = mutex:: Mutex :: new ( ) ;
944947 static mut COUNTER : u64 = 0 ;
945948
You can’t perform that action at this time.
0 commit comments