The major takeaway from this is that Rust will be making environment setters unsafe in the next edition. With luck, this will filter down into crates that trigger these crashes ( https://github.com/alexcrichton/openssl-probe/issues/30 filed upstream in the meantime).
People get trained to ignore the ____UNSAFE_payattention__nevermindthatthisappears50timesinthisfile___ blocks and prefixes This also shows up in web frameworks where Vue has the v-html directive and react has dangerouslySetInnerHTML. Vue definitely has it better.
C stdlib isn't threadsafe and even safe Rust didn't save us
51–60 of 370 posts
Re: C stdlib isn't threadsafe and even safe Rust didn't save us
#52Earlier quoted context omitted.
The man page says: > POSIX.1 does not require setenv() or unsetenv() to be reentrant. A non-reentrant function cannot be thread safe. In general (for POSIX, libc and many other libraries: if the docs do not explicitly say "this function is thread safe" they are not).
> A non-reentrant function cannot be thread safe. Actually, a non-reentrant function can be thread-safe. A common example of such a function in libc being malloc().
Re: C stdlib isn't threadsafe and even safe Rust didn't save us
#53Earlier quoted context omitted.
It's time to move beyond this attitude and make things safe by default. For example, Solaris has a safer version of setenv(). "It is ridiculous that this has been a known problem for so long. It has wasted thousands of hours of people's time, either debugging the problems, or debating what to do about it. We know how to fix the problem." https://www.evanjones.ca/setenv-is-not-thread-safe.html
You can't. You could wrap setenv in a mutex, but that's not good enough. It can still be called from different processes, which means you'd need to do a more expensive and complex syncing system to make it safe. That ballons out to other env related methods needing to honor the synchronization primitive in order for there to be a semblance of safety. However, you still end up in a scenario where you can call setenv g…
Re: C stdlib isn't threadsafe and even safe Rust didn't save us
#54It is weird that I got this right before Rust did. Because I use structured concurrency, I can make it so every thread has its own environment stack . To add to a new environment, I duplicate it, add the new variable, and push the new enviroment on the stack. Then I can use code blocks to delimit where that stack should be popped. [1] This is all perfectly safe, no `unsafe` required, and can even extend to other thin…
If you have 1) C FFI interop in Yao, there's still a chance you might have two C libraries cause a crash without your code even being involved.
Re: C stdlib isn't threadsafe and even safe Rust didn't save us
#55Earlier quoted context omitted.
Env vars are good if you treat them as read-only within the process
Yeah, setenv should probably just not exist, and environment variables should be only set when spawning new processes.
Ideally all libraries which use environment variables should have APIs allowing you to override the env variables without calling setenv(), but that isn't always the case.
Re: C stdlib isn't threadsafe and even safe Rust didn't save us
#56I wonder why it is so hard for Rust to implement its own safe stdlib independent of C.
Re: C stdlib isn't threadsafe and even safe Rust didn't save us
#57I wonder why it is so hard for Rust to implement its own safe stdlib independent of C.
It would be a tremendous amount of work, and would take years. Meanwhile, the problems are avoidable. It's not exactly the "rust way" to just remember and avoid problems, but everything in language design is compromises.
https://github.com/sunfishcode/eyra
Oh look:
> Why use Eyra? It fixes Rust's set_var unsoundness issue. The environment-variable implementation leaks memory internally (it is optional, but enabled by default), so setenv etc. are thread-safe.
Re: C stdlib isn't threadsafe and even safe Rust didn't save us
#58Earlier quoted context omitted.
> A non-reentrant function cannot be thread safe. Actually, a non-reentrant function can be thread-safe. A common example of such a function in libc being malloc().
By definition, a "reentrant function" is a function that may be invoked even when it has not returned yet from a previous invocation. So a non-reentrant function is a function that may not be invoked again between a previous invocation and returning from that invocation. When a function may be invoked from different threads, then it is certain that sometimes it will be invoked by a thread before returning from a prev…
Re: C stdlib isn't threadsafe and even safe Rust didn't save us
#59Earlier quoted context omitted.
It's time to move beyond this attitude and make things safe by default. For example, Solaris has a safer version of setenv(). "It is ridiculous that this has been a known problem for so long. It has wasted thousands of hours of people's time, either debugging the problems, or debating what to do about it. We know how to fix the problem." https://www.evanjones.ca/setenv-is-not-thread-safe.html
You can't. You could wrap setenv in a mutex, but that's not good enough. It can still be called from different processes, which means you'd need to do a more expensive and complex syncing system to make it safe. That ballons out to other env related methods needing to honor the synchronization primitive in order for there to be a semblance of safety. However, you still end up in a scenario where you can call setenv g…
Making global state, especially state that has no reason to be modified or even read very often like the env, thread safe is a trivial issue, well studied and understood. Could an intern do it? Probably not. Could literally any maintainer of a standard C library? Easily.
This is much more of a culture problem preventing such obvious flaws from being recognized as such.
Side-note: your set-then-get example is a theoretical problem in search of a use case. Why would you ever want to concurrently set an env var and expect to be guaranteed to read that same value? And even if this is a real thing that applications really use, exposing a new function to sync anything on the env mutex is, again, trivial. So, if you really needed that, you could do
lockenv
setenv
getenv
unlockenv
And problem solved.Re: C stdlib isn't threadsafe and even safe Rust didn't save us
#60Earlier quoted context omitted.
Yeah, setenv should probably just not exist, and environment variables should be only set when spawning new processes.
The problem is that applications sometimes need to set environment variables which will be read by libraries in the same process. This is safe to do during startup, but at no later times. Ideally all libraries which use environment variables should have APIs allowing you to override the env variables without calling setenv(), but that isn't always the case.