@@ -81,6 +81,10 @@ pub fn current_exe() -> io::Result<PathBuf> {
8181
8282static ENV_LOCK : RwLock < ( ) > = RwLock :: new ( ( ) ) ;
8383
84+ pub fn env_read_lock ( ) -> impl Drop {
85+ ENV_LOCK . read ( ) . unwrap_or_else ( PoisonError :: into_inner)
86+ }
87+
8488pub struct Env {
8589 iter : vec:: IntoIter < ( OsString , OsString ) > ,
8690}
@@ -134,7 +138,7 @@ pub fn env() -> Env {
134138 }
135139
136140 unsafe {
137- let _guard = ENV_LOCK . read ( ) ;
141+ let _guard = env_read_lock ( ) ;
138142 let mut result = Vec :: new ( ) ;
139143 if !environ. is_null ( ) {
140144 while !( * environ) . is_null ( ) {
@@ -168,17 +172,21 @@ pub fn env() -> Env {
168172pub fn getenv ( k : & OsStr ) -> Option < OsString > {
169173 // environment variables with a nul byte can't be set, so their value is
170174 // 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 ;
176178
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 ( )
182190}
183191
184192pub fn setenv ( k : & OsStr , v : & OsStr ) -> io:: Result < ( ) > {
0 commit comments