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.
This commit is contained in:
parent
da638b3a9f
commit
9530ba0fe2
@ -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)
|
||||
})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user