Description
Observing an environment variable concurrently with a call to setenv
constitutes a data race. Rust currently handles this by using a mutex, but that only protects against functions in std::env
. My interpretation of POSIX (which appears to be the same as the glibc developers') is that any libc function is allowed to call getenv
. This has already caused problems with getaddrinfo
in #27970.
Additionally, a large amount of C code calls getenv
but is otherwise thread-safe. While this isn't necessarily the standard library's issue, it's impossible for third-party libraries to soundly use this code without requiring the user to certify that this isn't an issue via an unsafe
block. Some examples of this happening in practice are in time-rs/time#293 and rust-lang/flate2-rs#272.
rustsec/advisory-db#926 had several proposals on how this could be handled brought up.
Make std::env::set_var
unsafe
This is arguably the cleanest solution to the issue. This could be considered a soundness fix, which would make it an option, but the ecosystem impact feels like it'd be too big.
Don't actually call setenv
std
could keep track of the environment itself, and make set_var
changes only visible to var
and subprocesses. This is probably the way to solve the issue with the least impact on existing code, but the behavior is somewhat unexpected and not zero-cost.
Only call setenv
in single-threaded code
This would reduce the impact further, but seems even less expected for negligible benefit.
Deprecate std::env::set_var
This would make it clear that setting an environment variable in the current process is discouraged. It could also be combined with not actually calling setenv
, which would be my preferred solution to this issue.