4 ms·
I think the argument was that the standard states that setenv is not thread safe, although from what I see it says that it does not have to be thread safe: T
by 4gotunameagain 2y ago
I think the argument was that the standard states that setenv is not thread safe, although from what I see it says that it does not have to be thread safe:
The setenv( ) function need not be thread-safe. A function that is not required to be thread-safe is not required to be reentrant.
https://www.open-std.org/jtc1/sc22/open/n4217.pdf https://www.open-std.org/jtc1/sc22/open/n4217.pdf.
Page.. 1860 :')
- HarHarVeryFunny 2y agoSure, but given that Linux defines the environment as state that's shared between threads, not having a thread-safe way of accessing it is hard to defend... Is "the standard says it doesn't NEED to be thread safe" the argument that the Linux libc maintainers are using for not enhancing it to be thread safe, or is it based on some technical or backwards compatibility issues in doing so ?
- debugnik 2y agoThe only thread-safe way to implement getenv/setenv as they currently exist is to leak the previous state when setenv allocates, such that existing pointers stay valid. The existing API simply lacks a mechanism to synchronize correctly. Leaking would be good enough for many use cases, but it would break long-running users of setenv (mainly those with libraries abusing env vars, as in TFA), and doesn't even solve how they interact with putenv and environ. This whole API is just cursed. Libc could of course get better APIs, like GetEnvironmentVariable on Windows, but that won't fix all existing code.
- HarHarVeryFunny 2y agoDo you mean pointers returned by getenv() ? Those could point to thread-local buffers that data gets copied into when getenv() is called.
- debugnik 2y agoOnly if we're willing to take for granted that a call to getenv invalidates the previous one. POSIX allows it, but I'm concerned about runtimes scheduling user tasks on the same thread. If current platforms are safely making a copy of getenv before allowing their scheduler to interrupt, then yes I'd be ok with your solution.
- HarHarVeryFunny 2y agoIf you wanted to avoid "only latest getenv pointer per thread is valid", then the thread local data structure could be a var-name-> buffer map rather than a single reused buffer. Worst case memory usage (all threads get all vars) is that you end up having a separate copy of the environment per thread, but it seems this is the best that can be done given the awful API.