3 ms·
Lots of C isn't thread safe, and that's the point. It's supposed to be close to the metal, and it's supposed to be small. If you want to add additional functi
by ChrisRR 3y ago
Lots of C isn't thread safe, and that's the point. It's supposed to be close to the metal, and it's supposed to be small. If you want to add additional functionality then that's on the user/library.
If we add thread safe/memory safe versions of every function, then we're moving away from C and into Rust territory.
C is a powerful language, but it's not a language designed to hold your hand.
Edit: Especially in this case where the environment is maintained by the OS, that puts the onus of safety on the OS to ensure that different processes can't modify and read the env simultaneously.
If you're worried about reading and writing the env in different threads within the same process, then you need to reconsider your design.
- rini17 3y agoWe're talking about C standard library here. Which has streams (struct FILE) that are threadsafe and use locks by default - even in single-threaded programs. They could have extended the interface to access the environment too. But idk, reasons.
- jstimpfle 3y agoContrary to fread(), getenv() does not copy data. It returns a pointer to memory that might be invalidated by the following setenv(). In other words, it can't be really made threadsafe -- it's fundamentally a thread-unsafe API. What could be done is offering an alternative, thread-safe API that takes an RW mutex on get/set, and get reads to a user-provided buffer. However, that would be complicated as well because the user can't know the size of any envvar, and getting the size before reading the var is racy. So maybe there needs to be env_lock()/env_unlock() and getenv_unlocked()/setenv_unlocked(). Or a version that locks and strdups() the var. But that still leaves the problem that existing software does not use this API. And really, why would you set envvars instead of global variables? Seriously? A data structure that is a list of KEY=VALUE formatted zero-terminated string pointers? Just don't do it. Use setenv() only at startup and after fork() and before exec(), done.
- rini17 3y agoWhy? Since there's no other global key-value store handy in C, environment will continue to be (ab)used. Simple as that. Better than makeshift k-v store with global variables full of pitfalls and buffer overflows, at any rate. I believe existing software would gladly migrate.
- jstimpfle 3y agoWhy would you need a generic global key-value store? One with excruciatingly bad performance (apart from the inherent thread-unsafety) that stores keys and values encoded in text form as KEY=VALUE? I've never needed such a thing. Much better to use proper globals, or to use hashes, maps, arrays, ... depending on the context. And why should it be _a_ global store, instead of a structure that you can instantiate as many times as you want (if you really need to, as a global)?
- lifthrasiir 3y agoMy design is perfect, but libraries have no idea and can and will break my perfect design. Joke aside though, for this reason thread safety is one of general requirements for the composability that any large enough software project would definitely need.
- another2another 3y agoI don't think C standard library particularly wanted to be problematic to use, but they just weren't prepared for multithreaded general programming, and tried to patch it with e.g. the _r() version of methods. An example where I recently made a change is localtime() where I changed to use the _r() variant after wrongly just calling localtime(), but only later realised they were using a global per-process buffer which might produce wrong results in my logging code (e.g. if another thread calls localtime then my time buffer would be updated after I populated it 2 seconds prior). Now the clib could have made a per thread TLS slot for each threads' time values without too much overhead, which would have automatically fixed any careless uses of localtime() in multiple threads, but instead opted for the separate thread safe function calls.
- SAI_Peregrinus 3y agoC is not supposed to be close to "the metal" unless that's a single-core unified-memory processor. It's supposed to be maximally portable while retaining reasonable performance, and it does that very well.
- andrewaylett 3y ago> It's supposed to be close to the metal, and it's supposed to be small. Unless you're developing for the PDP-11, I'm afraid I have some bad news for you. We absolutely want -- and occasionally get -- safe versions of unsafe functions, like strlcpy. And we rely on quite a lot of code to maintain the appearance that C is close to the metal.