11#![ deny( unsafe_op_in_unsafe_fn) ]
22
3- use crate :: any:: Any ;
43use crate :: error:: Error as StdError ;
54use crate :: ffi:: { CStr , OsStr , OsString } ;
65use crate :: fmt;
76use crate :: io;
87use crate :: marker:: PhantomData ;
8+ use crate :: ops:: Drop ;
99use crate :: os:: wasi:: prelude:: * ;
1010use crate :: path:: { self , PathBuf } ;
1111use 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
150161pub 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
181192pub 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> {
194205pub 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
203214pub 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