# Why C's setenv() and unsetenv() Are Not Thread-Safe

DevFeed: [Why C's setenv() and unsetenv() Are Not Thread-Safe](<https://devfeed.tech/articles/setenv-is-not-thread-safe-and-c-doesn-t-want-to-fix-it-20760.md>)

Original publisher: [Read original article](<https://www.evanjones.ca/setenv-is-not-thread-safe.html>)

Published: 2023-11-19T14:13:23Z

Content type: opinion

Language: en

Sources: [Evan Jones](<https://devfeed.tech/sources/evan-jones.md>)

Topics: [C](<https://devfeed.tech/topics/c.md>), [POSIX](<https://devfeed.tech/topics/posix.md>), [bug](<https://devfeed.tech/topics/bug.md>), [Concurrency](<https://devfeed.tech/topics/concurrency.md>), [Concurrent Programming](<https://devfeed.tech/topics/concurrent-programming.md>), [Go](<https://devfeed.tech/topics/go.md>), [Go Language](<https://devfeed.tech/topics/go-language.md>), [Rust](<https://devfeed.tech/topics/rust.md>)

Tags: [bug](<https://devfeed.tech/tags/bug.md>), [c](<https://devfeed.tech/tags/c.md>), [crash](<https://devfeed.tech/tags/crash.md>), [dns](<https://devfeed.tech/tags/dns.md>), [go](<https://devfeed.tech/tags/go.md>), [posix](<https://devfeed.tech/tags/posix.md>), [rust](<https://devfeed.tech/tags/rust.md>), [thread](<https://devfeed.tech/tags/thread.md>)

## AI overview

The article explains that C's setenv() and unsetenv() modify global environment state and can race with getenv(), causing crashes in multithreaded programs. It argues that the POSIX interface is difficult to use safely and has affected software such as Go and Rust.

## Source excerpt

You can't safely use the C setenv() or unsetenv() functions in a program that uses threads. Those functions modify global state, and can cause other threads calling getenv() to crash. This also causes crashes in other languages that use those C standard library functions, such as Go's os.Setenv (Go issue) and Rust's std::env::set_var() (Rust issue). I ran into this in a Go program, because Go's built-in DNS resolver can call C's getaddrinfo(), which uses environment variables. This cost me 2 days to track down and file the Go bug. Sadly, this problem has been known for decades. For example, an article from January 2017 said: "None of this is new, but we do re-discover it roughly every five years. See you in 2022." This was only one year off! (She wrote an update in October 2023 after I emailed her about my Go bug.) This is a flaw in the POSIX standard, which extends the C Standard to allow modifying environment varibles. The most infuriating part is that many people who could influence the standard or maintain the C libraries don't see this as a problem. The argument is that the specification clearly documents that setenv() cannot be used with threads. Therefore, if someone does this, the crashes are their fault. We should apparently read every function's specification carefully, not use software written by others, and not use threads. These are unrealistic assumptions in modern software. I think we should instead strive to create APIs that are hard to screw up, and evolve as the ecosystem changes. The C language and standard library continue to play an important role at the base of most software. We either need to figure out how to improve it, or we need to figure out how to abandon it. Why is setenv() not thread-safe? The biggest problem is that getenv() returns a char*, with no need for applications to free it later. One thread could be using this pointer when another thread changes the same environment variable using setenv() or unsetenv(). The getenv() function