-
Notifications
You must be signed in to change notification settings - Fork 47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Functions that modify the environment have undocumented safety requirements #112
Comments
Thank you for raising this! There will likely be a new For now, I will mark the safety documentation as a priority. |
This is what I have come up with for the rustdoc. @allan2 could you please review it? SafetyEven though this function is currently not marked as This function is safe to call in a single-threaded program. Also for any In multi-threaded programs, you must ensure there are no other threads |
Unfortunately this is going to apply to every public function as they all internally call |
Proposed SafetyThe majority of
|
On the Rust community discord, @5225225 suggested the idea of a |
This safety concern also does not apply to Windows, which apparently has thread-safe environment variables. |
I actually am growing to like this idea. Example#[dotenvy::main]
fn main() -> Result<(), AppError> {
tokio_main()
}
#[tokio::main]
async fn tokio_main() -> Result<(), AppError> {
// app goes here
// ...
Ok(())
} |
This is a very important issue that will change the future of dotenvy. The next release of dotenvy will offer both a safe API (which does not modify the environment) and an unsafe API (which does modify the environment via I also really like the attribute macro. It is the most ergonomic way to call the loading function before initiating the multi-threaded runtime. #[dotenvy::load(config = "tbd")]
#[tokio::main]
async fn main() {
foo();
} |
I think we should add a safety notice now for the existing API. @allan2 would you be OK with me adding the rustdoc and readme additions above? |
Note that the unsafety is unrelated to Rust 2024. It's just as unsafe in Rust 2015, 2018, 2021, it's just missing the |
There is a new API in the v0.16 branch. let loader = EnvLoader::from_path(path).sequence(EnvSequence::FilesThenEnv);
// does not modify environment
let env_map: HashMap<String, String> = loader.load()?;
// modifies environment using `set_var`
let env_map: HashMap<String, String> = unsafe { loader.load_and_modify() }?; There is also an attribute macro that is thread-safe. // this loads from the file into the environment before the async runtime is started
#[dotenvy::load]
#[tokio::main]
async fn main() {
println!("inside async runtime");
} There are examples for tokio without macro and tokio with macro. So there is progress on this front. Doc still have to be added though, so I will leave this issue open. |
The typical usage of calling
dotenvy::dotenvy();
to load and setup the programs environment variables is missing certain safety requirements, namely that it must be done before any other threads in the program are spawned. This is documented in the stdlib, andset_var
&remove_var
are slated to become unsafe in Rust 2024 for this reason.A common way to violate these requirements is the following program:
This expands to the following code:
Notice how the
dotenvy
call gets moved into an async block and run after the tokio runtime threads have been spawned. This is unsound in theory and practice, since tokio internally accesses the environment prior to this point (to allow configuring the number of worker threads through an env var).The documentation for functions that modify the environment at least need to reproduce the safety requirements from the stdlib, and very probably should become unsafe to mirror the Rust 2024 developments.
The text was updated successfully, but these errors were encountered: