summary refs log tree commit diff
path: root/library/std/src/sys
diff options
context:
space:
mode:
authorAndrew Brown <andrew.brown@intel.com>2022-09-29 11:17:15 -0700
committerAndrew Brown <andrew.brown@intel.com>2022-10-10 09:01:42 -0700
commit9530ba0fe2118d9a60e16861faad29ec5803d3f9 (patch)
tree167a9919b64cd8dabad62f7c202d4da656a9a85e /library/std/src/sys
parentda638b3a9f32974c41439be6834670d7a438faa3 (diff)
downloadrust-9530ba0fe2118d9a60e16861faad29ec5803d3f9.tar.gz
rust-9530ba0fe2118d9a60e16861faad29ec5803d3f9.zip
Implement `env_lock` with `RwLock`
Copying the approach of the Unix target, this change uses the standard
`RwLock` to protect against concurrent access of libc's environment.
This locking is only enabled when WebAssembly's `atomics` feature is
also enabled.
Diffstat (limited to 'library/std/src/sys')
-rw-r--r--library/std/src/sys/wasi/os.rs35
1 files changed, 23 insertions, 12 deletions
diff --git a/library/std/src/sys/wasi/os.rs b/library/std/src/sys/wasi/os.rs
index b340061cb3d..cffe1e32308 100644
--- a/library/std/src/sys/wasi/os.rs
+++ b/library/std/src/sys/wasi/os.rs
@@ -1,11 +1,11 @@
 #![deny(unsafe_op_in_unsafe_fn)]
 
-use crate::any::Any;
 use crate::error::Error as StdError;
 use crate::ffi::{CStr, OsStr, OsString};
 use crate::fmt;
 use crate::io;
 use crate::marker::PhantomData;
+use crate::ops::Drop;
 use crate::os::wasi::prelude::*;
 use crate::path::{self, PathBuf};
 use crate::str;
@@ -24,13 +24,24 @@ mod libc {
     }
 }
 
-pub unsafe fn env_lock() -> impl Any {
-    cfg_if::cfg_if! {
-        if #[cfg(target_feature = "atomics")] {
-            todo!()
-        } else {
-            // No need for a lock if we're single-threaded, but this function will need
-            // to get implemented for multi-threaded scenarios
+cfg_if::cfg_if! {
+    if #[cfg(target_feature = "atomics")] {
+        // Access to the environment must be protected by a lock in multi-threaded scenarios.
+        use crate::sync::{PoisonError, RwLock};
+        static ENV_LOCK: RwLock<()> = RwLock::new(());
+        pub fn env_read_lock() -> impl Drop {
+            ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
+        }
+        pub fn env_write_lock() -> impl Drop {
+            ENV_LOCK.write().unwrap_or_else(PoisonError::into_inner)
+        }
+    } else {
+        // No need for a lock if we are single-threaded.
+        pub fn env_read_lock() -> impl Drop {
+            ()
+        }
+        pub fn env_write_lock() -> impl Drop {
+            ()
         }
     }
 }
@@ -149,7 +160,7 @@ impl Iterator for Env {
 
 pub fn env() -> Env {
     unsafe {
-        let _guard = env_lock();
+        let _guard = env_read_lock();
         let mut environ = libc::environ;
         let mut result = Vec::new();
         if !environ.is_null() {
@@ -180,7 +191,7 @@ pub fn env() -> Env {
 
 pub fn getenv(k: &OsStr) -> Option<OsString> {
     let s = run_with_cstr(k.as_bytes(), |k| unsafe {
-        let _guard = env_lock();
+        let _guard = env_read_lock();
         Ok(libc::getenv(k.as_ptr()) as *const libc::c_char)
     })
     .ok()?;
@@ -194,7 +205,7 @@ pub fn getenv(k: &OsStr) -> Option<OsString> {
 pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
     run_with_cstr(k.as_bytes(), |k| {
         run_with_cstr(v.as_bytes(), |v| unsafe {
-            let _guard = env_lock();
+            let _guard = env_write_lock();
             cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop)
         })
     })
@@ -202,7 +213,7 @@ pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
 
 pub fn unsetenv(n: &OsStr) -> io::Result<()> {
     run_with_cstr(n.as_bytes(), |nbuf| unsafe {
-        let _guard = env_lock();
+        let _guard = env_write_lock();
         cvt(libc::unsetenv(nbuf.as_ptr())).map(drop)
     })
 }