Earlier quoted context omitted.
The p in pthreads stands for Posix. I.e., uh, Posix is neither set in stone, nor entirely predates threads.
I am old enough to remeber when UNIX only had processes, and several thread designs were being discussed until eventually pthreads one design won. POSIX predates adoption of threads in the UNIX world.
C stdlib isn't threadsafe and even safe Rust didn't save us
331–340 of 370 posts
Re: C stdlib isn't threadsafe and even safe Rust didn't save us
#332Re: C stdlib isn't threadsafe and even safe Rust didn't save us
#333Earlier quoted context omitted.
It really does not look like a good idea to setenv() . The very notion is quite terrifying. Messing with a bunch of globals, that other code knows about as well? Nuh-uh. The thing is, the OP people weren't doing that at all, it was some irresponsible library maintainers. If your code does that, you have to include something like the "surgeon general's warning" everywhere: "CAREFUL: USING THIS LIBRARY MAY CAUSE TERMIN…
Sadly, it's often the only way to adjust certain behaviors of certain libraries.
Re: C stdlib isn't threadsafe and even safe Rust didn't save us
#334Earlier quoted context omitted.
What is wrong with main setting those things first and then starting your main program? That is what everyone else does.
Not “everyone” does that. You have individual files doing their own initialization when they get loaded. Including loading other files or modules. They might do it for testing purposes.
Re: C stdlib isn't threadsafe and even safe Rust didn't save us
#335Earlier quoted context omitted.
You also need the apps installed on whatever then, and enough CPU power to run those apps. I'm not saying you are wrong, but there is a lot of nuance here.
For CPU power, a Raspberry Pi today is faster than servers that ran whole medium to large businesses 20 years ago. Much of what people do with SaaS involves backend processes that could run on a 1990s era PC. There are exceptions, like large AI models and huge databases like web search, though in the case of AI models I can run pretty decent ones locally already, but on an admittedly expensive laptop. If the rate at…
Of course the elephant in the room remains: I need my data where I am.
Re: C stdlib isn't threadsafe and even safe Rust didn't save us
#336The 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).
But that won't actually fix the underlying problem, namely that getenv and setenv (or unsetenv, probably) cannot safely be called from different threads. It seems like the only reliable way to fix this is to change these functions so that they exclusively acquire a mutex.
stdenvlock(); // imaginary function added to ISO C or POSIX
char *home = getenv("HOME");
char *home_copy = strdup(home);
stdenvunlock(); // only here can we unlock
// home pointer is now indeterminate
Other solutions:1. Put the above sequence into a function, and don't expose the mutex. Thread-safe code must use:
char *home = dupenv("HOME"); // imaginary function; caller responsible for freeing.
2. Provide environment lookup into a buffer: getenvbuf("HOME", mybuf, sizeof mybuf); // returns some value that helps to resize the buffer
All functions that retain pointers out of the classic getenv remain unsafe.A mutex can be provided to those applications that want to manipulate the environ array directly, or use getenv and setenv, or any combinations of these.
The main problem is all the code out there using getenv.
Re: C stdlib isn't threadsafe and even safe Rust didn't save us
#337You run into a problem if you keep using a string returned by getenv after calling another environment function: including possibly getenv itself!
However, it's easy to just strdup the result of getenv; that defends against the issue in a single-threaded program.
Re: C stdlib isn't threadsafe and even safe Rust didn't save us
#338Earlier quoted context omitted.
But that won't actually fix the underlying problem, namely that getenv and setenv (or unsetenv, probably) cannot safely be called from different threads. It seems like the only reliable way to fix this is to change these functions so that they exclusively acquire a mutex.
I have a different perspective: the underlying problem is calling setenv(). As far as I'm concerned, the environment is a read-only input parameter set on process creation like argv. It's not a mechanism for exchanging information within a process, as used here with SSL_CERT_FILE. And remember that the exec* family of calls has a version with an envp argument, which is what should be used if a child process is to be…
"The getenv function returns a pointer to a string associated with the matched list member. The string pointed to shall not be modified by the program, but can be overwritten by a subsequent call to the getenv function."
In a single threaded virtual machine, you can immediately duplicate the string returned by getenv and stop using it, right there.
Under threads, getenv is not required to be safe.
I think that with some care, it may be; an environment implementation could guarantee that a non-mutating operation like getenv doesn't invalidate any previously returned strings.
I think POSIX does that. It allows getenv to reallocate the environ array, but not the strings themselves:
"Applications can change the entire environment in a single operation by assigning the environ variable to point to an array of character pointers to the new environment strings. After assigning a new value to environ, applications should not rely on the new environment strings remaining part of the environment, as a call to getenv(), secure_getenv(), [XSI] [Option Start] putenv(), [Option End] setenv(), unsetenv(), or any function that is dependent on an environment variable may, on noticing that environ has changed, copy the environment strings to a new array and assign environ to point to it."
environ is documented together with the exec family of functions; that's where this is found.
So whereas there are things not to like about environ, it can be the basis for thread safety of getenv in an application that doesn't mutate the environment.
Re: C stdlib isn't threadsafe and even safe Rust didn't save us
#339Earlier quoted context omitted.
But that won't actually fix the underlying problem, namely that getenv and setenv (or unsetenv, probably) cannot safely be called from different threads. It seems like the only reliable way to fix this is to change these functions so that they exclusively acquire a mutex.
No amount of locking can make the getenv API thread-safe, because it returns a pointer which gets invalidated by setenv, but lacks a way to release ownership over it and unblock setenv safely (or to free a returned copy). So setenv's existence makes getenv inherently unsafe unless you can ensure the entire application is at a safe point to use them.
Re: C stdlib isn't threadsafe and even safe Rust didn't save us
#340Earlier quoted context omitted.
But that won't actually fix the underlying problem, namely that getenv and setenv (or unsetenv, probably) cannot safely be called from different threads. It seems like the only reliable way to fix this is to change these functions so that they exclusively acquire a mutex.
Please no. If your program wants to use the environment as an out-of-band global var for cross thread communication, you can make your own mutex.