about summary refs log tree commit diff
path: root/src/libstd/io
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2018-08-06 12:45:27 +0200
committerRalf Jung <post@ralfj.de>2018-08-06 12:54:44 +0200
commitd3d31105e99f5265880d0f010436ed5c6baab034 (patch)
tree02ea7c780c9e844e81763cecc19b9c9ec8604391 /src/libstd/io
parent7c98d2e63f732682b057c8c453b08f9e12b262e6 (diff)
downloadrust-d3d31105e99f5265880d0f010436ed5c6baab034.tar.gz
rust-d3d31105e99f5265880d0f010436ed5c6baab034.zip
clarify partially initialized Mutex issues
Diffstat (limited to 'src/libstd/io')
-rw-r--r--src/libstd/io/lazy.rs7
1 files changed, 7 insertions, 0 deletions
diff --git a/src/libstd/io/lazy.rs b/src/libstd/io/lazy.rs
index d357966be92..09b2ddcbcac 100644
--- a/src/libstd/io/lazy.rs
+++ b/src/libstd/io/lazy.rs
@@ -27,6 +27,9 @@ unsafe impl<T> Sync for Lazy<T> {}
 
 impl<T: Send + Sync + 'static> Lazy<T> {
     pub const fn new(init: fn() -> Arc<T>) -> Lazy<T> {
+        // `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`.
         Lazy {
             lock: Mutex::new(),
             ptr: Cell::new(ptr::null_mut()),
@@ -48,6 +51,7 @@ impl<T: Send + Sync + 'static> Lazy<T> {
         }
     }
 
+    // Must only be called with `lock` held
     unsafe fn init(&'static self) -> Arc<T> {
         // If we successfully register an at exit handler, then we cache the
         // `Arc` allocation in our own internal box (it will get deallocated by
@@ -60,6 +64,9 @@ impl<T: Send + Sync + 'static> Lazy<T> {
             };
             drop(Box::from_raw(ptr))
         });
+        // This could reentrantly call `init` again, which is a problem
+        // because our `lock` allows reentrancy!
+        // FIXME: Add argument why this is okay.
         let ret = (self.init)();
         if registered.is_ok() {
             self.ptr.set(Box::into_raw(Box::new(ret.clone())));