Skip to content

Commit d3d3110

Browse files
committed
clarify partially initialized Mutex issues
1 parent 7c98d2e commit d3d3110

File tree

8 files changed

+33
-2
lines changed

8 files changed

+33
-2
lines changed

src/libstd/io/lazy.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ unsafe impl<T> Sync for Lazy<T> {}
2727

2828
impl<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())));

src/libstd/sys/unix/args.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff 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) {

src/libstd/sys/unix/mutex.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ unsafe impl Sync for Mutex {}
2525
#[allow(dead_code)] // sys isn't exported yet
2626
impl 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]

src/libstd/sys/unix/os.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ use sys::fd;
3333
use vec;
3434

3535
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`.
3639
static ENV_LOCK: Mutex = Mutex::new();
3740

3841

src/libstd/sys_common/at_exit_imp.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff 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`.
2629
static LOCK: Mutex = Mutex::new();
2730
static 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 {

src/libstd/sys_common/mutex.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff 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

src/libstd/sys_common/thread_local.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff 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);

src/libstd/thread/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,9 @@ pub struct ThreadId(u64);
940940
impl 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

0 commit comments

Comments
 (0)