Skip to main content

Module test_env

Module test_env 

Source
Expand description

Serialized, panic-safe access to process-global environment variables.

Test-only in purpose, compiled always: mur-agent-runtime’s tests need it and a #[cfg(test)] item in this crate is invisible to them. It is ~60 lines of dead code in a release binary.

§Why one lock for every variable

setenv(3) may reallocate the environ array, so a concurrent getenv anywhere in the process — including inside libc or a dependency, for a variable this test has never heard of — can read freed memory. That is why Rust 2024 made std::env::set_var unsafe. The hazard is the array, not the name, so a per-variable lock (which this replaces) gives false comfort: it orders writers of MUR_HOME against each other and does nothing about the reader of PATH two threads over.

§What wrapping the MutexGuard costs

clippy::await_holding_lock fires on a bare std::sync::MutexGuard held across an .await; it does not see one inside a struct, so it is silent here. The hazard it warns about — a task blocking the thread its holder needs to resume on — does not arise for #[tokio::test], which gives each test its own current-thread runtime on its own thread. Holding this guard across an await in production code would be a different matter, and the lint would not tell you.

§Why a guard rather than a save/restore pair

The pattern this replaces saved the prior value, set the variable, ran the test, then restored — with the restore after the assertions. A failing assertion panics past it, so the variable outlives the TempDir it points at, and a std::sync::Mutex held across that panic is poisoned for every test after it. One failed assertion became a file of failures that named the lock instead of the bug. Restoring in Drop is what makes the restore actually run; tolerating poison is what keeps the cascade from starting.

Structs§

EnvGuard
Holds the process’s environment lock and restores every variable it touched when dropped — including back to absent.