18 ms·
What about using a linked list for variables added after the start of the process, which can be implemented atomically? Then once it gets "too long", a thread e
by Asooka 2y ago
What about using a linked list for variables added after the start of the process, which can be implemented atomically? Then once it gets "too long", a thread executing setenv could construct a new hashmap and replace the pointer to the old one with the pointer to the new one atomically, all without locking? To prevent two threads from rehashing at the same time, use an atomic flag for whether a thread is rehashing right now. That means if other threads call setenv in the meantime, the extra added variables would be appended to the list to be processed by a later setenv call (if one happens). That list could grow unbounded if enough threads call setenv quickly enough, but I think the simplicity of atomically swapping pointers might be worth it and setenv isn't called very frequently.
- jeffparsons 2y agoI like this approach, because it lets everything Just Work without anyone outside of the implementation having to think about it at all, and only incurs meaningful overhead if you're doing something really silly, but crucially still won't break — it'll just be slightly slow. That feels like the right trade-off.
- sunshowers 2y agoAs far as I'm concerned this is the only correct way to do it. I believe illumos does this, which is why its env functions are thread safe and have been for decades.
- fweimer 2y agoPOSIX requires that the environment variables can be access as an array, through the environ variable. This array is expected to be used with POSIX interfaces such as posix_spawn and execve. If the array already has to exist, why not use it in getenv? A purely hash-based implementation is not possible because there is putenv, and some applications expect modifications of environ to be visible via getenv.