1
1
#![ deny( unsafe_op_in_unsafe_fn) ]
2
2
3
- use crate :: any:: Any ;
4
3
use crate :: error:: Error as StdError ;
5
4
use crate :: ffi:: { CStr , OsStr , OsString } ;
6
5
use crate :: fmt;
7
6
use crate :: io;
8
7
use crate :: marker:: PhantomData ;
8
+ use crate :: ops:: Drop ;
9
9
use crate :: os:: wasi:: prelude:: * ;
10
10
use crate :: path:: { self , PathBuf } ;
11
11
use crate :: str;
@@ -24,13 +24,24 @@ mod libc {
24
24
}
25
25
}
26
26
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
+ ( )
34
45
}
35
46
}
36
47
}
@@ -149,7 +160,7 @@ impl Iterator for Env {
149
160
150
161
pub fn env ( ) -> Env {
151
162
unsafe {
152
- let _guard = env_lock ( ) ;
163
+ let _guard = env_read_lock ( ) ;
153
164
let mut environ = libc:: environ;
154
165
let mut result = Vec :: new ( ) ;
155
166
if !environ. is_null ( ) {
@@ -180,7 +191,7 @@ pub fn env() -> Env {
180
191
181
192
pub fn getenv ( k : & OsStr ) -> Option < OsString > {
182
193
let s = run_with_cstr ( k. as_bytes ( ) , |k| unsafe {
183
- let _guard = env_lock ( ) ;
194
+ let _guard = env_read_lock ( ) ;
184
195
Ok ( libc:: getenv ( k. as_ptr ( ) ) as * const libc:: c_char )
185
196
} )
186
197
. ok ( ) ?;
@@ -194,15 +205,15 @@ pub fn getenv(k: &OsStr) -> Option<OsString> {
194
205
pub fn setenv ( k : & OsStr , v : & OsStr ) -> io:: Result < ( ) > {
195
206
run_with_cstr ( k. as_bytes ( ) , |k| {
196
207
run_with_cstr ( v. as_bytes ( ) , |v| unsafe {
197
- let _guard = env_lock ( ) ;
208
+ let _guard = env_write_lock ( ) ;
198
209
cvt ( libc:: setenv ( k. as_ptr ( ) , v. as_ptr ( ) , 1 ) ) . map ( drop)
199
210
} )
200
211
} )
201
212
}
202
213
203
214
pub fn unsetenv ( n : & OsStr ) -> io:: Result < ( ) > {
204
215
run_with_cstr ( n. as_bytes ( ) , |nbuf| unsafe {
205
- let _guard = env_lock ( ) ;
216
+ let _guard = env_write_lock ( ) ;
206
217
cvt ( libc:: unsetenv ( nbuf. as_ptr ( ) ) ) . map ( drop)
207
218
} )
208
219
}
0 commit comments