@@ -81,6 +81,10 @@ pub fn current_exe() -> io::Result<PathBuf> {
81
81
82
82
static ENV_LOCK : RwLock < ( ) > = RwLock :: new ( ( ) ) ;
83
83
84
+ pub fn env_read_lock ( ) -> impl Drop {
85
+ ENV_LOCK . read ( ) . unwrap_or_else ( PoisonError :: into_inner)
86
+ }
87
+
84
88
pub struct Env {
85
89
iter : vec:: IntoIter < ( OsString , OsString ) > ,
86
90
}
@@ -134,7 +138,7 @@ pub fn env() -> Env {
134
138
}
135
139
136
140
unsafe {
137
- let _guard = ENV_LOCK . read ( ) ;
141
+ let _guard = env_read_lock ( ) ;
138
142
let mut result = Vec :: new ( ) ;
139
143
if !environ. is_null ( ) {
140
144
while !( * environ) . is_null ( ) {
@@ -168,17 +172,21 @@ pub fn env() -> Env {
168
172
pub fn getenv ( k : & OsStr ) -> Option < OsString > {
169
173
// environment variables with a nul byte can't be set, so their value is
170
174
// always None as well
171
- let s = run_with_cstr ( k. as_bytes ( ) , |k| {
172
- let _guard = ENV_LOCK . read ( ) ;
173
- Ok ( unsafe { libc:: getenv ( k. as_ptr ( ) ) } as * const libc:: c_char )
174
- } )
175
- . ok ( ) ?;
175
+ run_with_cstr ( k. as_bytes ( ) , |k| {
176
+ let _guard = env_read_lock ( ) ;
177
+ let v = unsafe { libc:: getenv ( k. as_ptr ( ) ) } as * const libc:: c_char ;
176
178
177
- if s. is_null ( ) {
178
- None
179
- } else {
180
- Some ( OsStringExt :: from_vec ( unsafe { CStr :: from_ptr ( s) } . to_bytes ( ) . to_vec ( ) ) )
181
- }
179
+ if v. is_null ( ) {
180
+ Ok ( None )
181
+ } else {
182
+ // SAFETY: `v` cannot be mutated while executing this line since we've a read lock
183
+ let bytes = unsafe { CStr :: from_ptr ( v) } . to_bytes ( ) . to_vec ( ) ;
184
+
185
+ Ok ( Some ( OsStringExt :: from_vec ( bytes) ) )
186
+ }
187
+ } )
188
+ . ok ( )
189
+ . flatten ( )
182
190
}
183
191
184
192
pub fn setenv ( k : & OsStr , v : & OsStr ) -> io:: Result < ( ) > {
0 commit comments