# Thread-safe environment variable mutation

**URL:** <https://internals.rust-lang.org/t/thread-safe-environment-variable-mutation/17817>\
**Category:** Uncategorized\
**Created:** [November 22, 2022, 9:57pm UTC](https://internals.rust-lang.org/t/thread-safe-environment-variable-mutation/17817 "2022-11-22T21:57:06Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![zackw](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/zackw/32/2071_2.png) [@zackw](https://internals.rust-lang.org/u/zackw)\
**Post date:** [November 22, 2022, 9:57pm UTC](https://internals.rust-lang.org/t/thread-safe-environment-variable-mutation/17817/1 "2022-11-22T21:57:06Z")

</div>

Almost a year ago (yikes!) in the "[Synchronized FFI access to POSIX environment variable functions](https://internals.rust-lang.org/t/synchronized-ffi-access-to-posix-environment-variable-functions/15475)" thread, I promised to write a proposal for changes to the POSIX specification that would allow thread-safe read-write access to environment variables. I have _finally_ gotten around to this, and I thought I would give IRLO a chance to kibitz it before I start showing it to C library implementors.

[https://www.owlfolio.org/development/thread-safe-environment-variable-mutation-working-draft-2022-15/](https://www.owlfolio.org/development/thread-safe-environment-variable-mutation-working-draft-2022-15/)

My blog doesn't have comments, so for now, feedback here is fine. (Once I do start showing it to C library people, feedback will probably need to move to `libc-alpha@sourceware.org` or some related mailing list.)

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [November 22, 2022, 11:08pm UTC](https://internals.rust-lang.org/t/thread-safe-environment-variable-mutation/17817/2 "2022-11-22T23:08:01Z")

</div>

Looks great!

A few bits of feedback on corner cases and rationale:

- `env_next` should document what happens if you call it _again_ after it returns NULL. That way, users and language bindings know whether they need to special-case this themselves. Ideally, it should return NULL repeatedly rather than invoking UB in this case.
- The rationale for `env_lookup` returning a string that includes the `NAME=` seems implicit. On the surface, this seems error-prone for usages that primarily want `getenv`; if you just passed the `NAME` you know what it is. And it'd be _possible_ for the data structure to index based on the pointer value to the _value_ rather than the NAME=value. I get the impression the rationale is to allow for passing it back to `putenv` and to simplify the implementation, but it seems worth documenting that rationale and documenting what the best alternative would be and the upsides and downsides of that alternative.
  - In particular, optimizing for the common case of retrieving a value rather than the uncommon case of subsequently passing it to putenv, env\_lookup could return a pointer to the value but guarantee that `NAME=` appears before it, so that if you want to call putenv you could _subtract_ that offset.
  - Alternatively, this proposal could hook `setenv` rather than `putenv`, and then do lookups based on the value.

- It doesn't seem _inherently_ required that a read lock held by `ENV_ITER` couldn't be passed from one thread to another. Many threading systems have locks that can be taken by one thread and released by another, and there are also alternate implementations that don't require a read lock (see the next bullet). It'd be nice if the Rust wrapper around `ENV_ITER` could be `Send`. How awful would it be for the spec to _require_ that `ENV_ITER` be usable from multiple threads (though only one at a time)?
- How important is the requirement that `env_iter` _snapshot_ the environment such that new changes aren't visible, rather than just requiring that it iterates without crashing and returns pointers that won't be modified, even in the face of concurrent modifications? That would allow for qsbr-based implementations, such as storing the environment in a concurrent hash table. And it'd eliminate the requirement for a full read lock and associated deadlock.
- Consider using "must not" rather than "may not", for clarity.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [February 20, 2023, 11:08pm UTC](https://internals.rust-lang.org/t/thread-safe-environment-variable-mutation/17817/3 "2023-02-20T23:08:07Z")

</div>

Closed on February 20, 2023, 11:08pm UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
