Skip to content

Commit 9530ba0

Browse files
committed
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.
1 parent da638b3 commit 9530ba0

File tree

1 file changed

+23
-12
lines changed
  • library/std/src/sys/wasi

1 file changed

+23
-12
lines changed

library/std/src/sys/wasi/os.rs

+23-12
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#![deny(unsafe_op_in_unsafe_fn)]
22

3-
use crate::any::Any;
43
use crate::error::Error as StdError;
54
use crate::ffi::{CStr, OsStr, OsString};
65
use crate::fmt;
76
use crate::io;
87
use crate::marker::PhantomData;
8+
use crate::ops::Drop;
99
use crate::os::wasi::prelude::*;
1010
use crate::path::{self, PathBuf};
1111
use crate::str;
@@ -24,13 +24,24 @@ mod libc {
2424
}
2525
}
2626

27-
pub unsafe fn env_lock() -> impl Any {
28-
cfg_if::cfg_if! {
29-
if #[cfg(target_feature = "atomics")] {
30-
todo!()
31-
} else {
32-
// No need for a lock if we're single-threaded, but this function will need
33-
// to get implemented for multi-threaded scenarios
27+
cfg_if::cfg_if! {
28+
if #[cfg(target_feature = "atomics")] {
29+
// Access to the environment must be protected by a lock in multi-threaded scenarios.
30+
use crate::sync::{PoisonError, RwLock};
31+
static ENV_LOCK: RwLock<()> = RwLock::new(());
32+
pub fn env_read_lock() -> impl Drop {
33+
ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
34+
}
35+
pub fn env_write_lock() -> impl Drop {
36+
ENV_LOCK.write().unwrap_or_else(PoisonError::into_inner)
37+
}
38+
} else {
39+
// No need for a lock if we are single-threaded.
40+
pub fn env_read_lock() -> impl Drop {
41+
()
42+
}
43+
pub fn env_write_lock() -> impl Drop {
44+
()
3445
}
3546
}
3647
}
@@ -149,7 +160,7 @@ impl Iterator for Env {
149160

150161
pub fn env() -> Env {
151162
unsafe {
152-
let _guard = env_lock();
163+
let _guard = env_read_lock();
153164
let mut environ = libc::environ;
154165
let mut result = Vec::new();
155166
if !environ.is_null() {
@@ -180,7 +191,7 @@ pub fn env() -> Env {
180191

181192
pub fn getenv(k: &OsStr) -> Option<OsString> {
182193
let s = run_with_cstr(k.as_bytes(), |k| unsafe {
183-
let _guard = env_lock();
194+
let _guard = env_read_lock();
184195
Ok(libc::getenv(k.as_ptr()) as *const libc::c_char)
185196
})
186197
.ok()?;
@@ -194,15 +205,15 @@ pub fn getenv(k: &OsStr) -> Option<OsString> {
194205
pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
195206
run_with_cstr(k.as_bytes(), |k| {
196207
run_with_cstr(v.as_bytes(), |v| unsafe {
197-
let _guard = env_lock();
208+
let _guard = env_write_lock();
198209
cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop)
199210
})
200211
})
201212
}
202213

203214
pub fn unsetenv(n: &OsStr) -> io::Result<()> {
204215
run_with_cstr(n.as_bytes(), |nbuf| unsafe {
205-
let _guard = env_lock();
216+
let _guard = env_write_lock();
206217
cvt(libc::unsetenv(nbuf.as_ptr())).map(drop)
207218
})
208219
}

0 commit comments

Comments
 (0)