diff options
| author | Ralf Jung <post@ralfj.de> | 2018-08-06 12:45:27 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2018-08-06 12:54:44 +0200 |
| commit | d3d31105e99f5265880d0f010436ed5c6baab034 (patch) | |
| tree | 02ea7c780c9e844e81763cecc19b9c9ec8604391 /src/libstd/sys_common | |
| parent | 7c98d2e63f732682b057c8c453b08f9e12b262e6 (diff) | |
| download | rust-d3d31105e99f5265880d0f010436ed5c6baab034.tar.gz rust-d3d31105e99f5265880d0f010436ed5c6baab034.zip | |
clarify partially initialized Mutex issues
Diffstat (limited to 'src/libstd/sys_common')
| -rw-r--r-- | src/libstd/sys_common/at_exit_imp.rs | 6 | ||||
| -rw-r--r-- | src/libstd/sys_common/mutex.rs | 4 | ||||
| -rw-r--r-- | src/libstd/sys_common/thread_local.rs | 3 |
3 files changed, 13 insertions, 0 deletions
diff --git a/src/libstd/sys_common/at_exit_imp.rs b/src/libstd/sys_common/at_exit_imp.rs index b28a4d2f8be..633605039af 100644 --- a/src/libstd/sys_common/at_exit_imp.rs +++ b/src/libstd/sys_common/at_exit_imp.rs @@ -23,6 +23,9 @@ type Queue = Vec<Box<dyn FnBox()>>; // on poisoning and this module needs to operate at a lower level than requiring // the thread infrastructure to be in place (useful on the borders of // initialization/destruction). +// `LOCK` is never initialized fully, so this mutex is reentrant! +// Do not use it in a way that might be reentrant, that could lead to +// aliasing `&mut`. static LOCK: Mutex = Mutex::new(); static mut QUEUE: *mut Queue = ptr::null_mut(); @@ -72,6 +75,9 @@ pub fn push(f: Box<dyn FnBox()>) -> bool { unsafe { let _guard = LOCK.lock(); if init() { + // This could reentrantly call `push` again, which is a problem because + // `LOCK` allows reentrancy! + // FIXME: Add argument why this is okay. (*QUEUE).push(f); true } else { diff --git a/src/libstd/sys_common/mutex.rs b/src/libstd/sys_common/mutex.rs index 608355b7d70..77a33e4c6be 100644 --- a/src/libstd/sys_common/mutex.rs +++ b/src/libstd/sys_common/mutex.rs @@ -24,11 +24,15 @@ impl Mutex { /// /// Behavior is undefined if the mutex is moved after it is /// first used with any of the functions below. + /// Also, the mutex might not be fully functional without calling + /// `init`! For example, on unix, the mutex is reentrant + /// until `init` reconfigures it appropriately. pub const fn new() -> Mutex { Mutex(imp::Mutex::new()) } /// Prepare the mutex for use. /// /// This should be called once the mutex is at a stable memory address. + /// It must not be called concurrently with any other operation. #[inline] pub unsafe fn init(&mut self) { self.0.init() } diff --git a/src/libstd/sys_common/thread_local.rs b/src/libstd/sys_common/thread_local.rs index 75f6b9ac7fd..2cc5372e268 100644 --- a/src/libstd/sys_common/thread_local.rs +++ b/src/libstd/sys_common/thread_local.rs @@ -161,6 +161,9 @@ impl StaticKey { // Additionally a 0-index of a tls key hasn't been seen on windows, so // we just simplify the whole branch. if imp::requires_synchronized_create() { + // `INIT_LOCK` is never initialized fully, so this mutex is reentrant! + // Do not use it in a way that might be reentrant, that could lead to + // aliasing `&mut`. static INIT_LOCK: Mutex = Mutex::new(); let _guard = INIT_LOCK.lock(); let mut key = self.key.load(Ordering::SeqCst); |
