On 1/3/23 2:11 PM, Niall Douglas via SG16 wrote:
getenv() is weirdly enough not async signal safe. Most will consider
that unimportant, which is true until suddenly it is extremely 
important. It would be really great if C++'s implementation gained async 
signal safety.

Agreed, though I think it is unsurprising that getenv() is not async-signal-safe. POSIX states:

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(), [XSI] putenv(), 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.

Any application that directly modifies the pointers to which the environ variable points has undefined behavior.

Conforming multi-threaded applications shall not use the environ variable to access or modify any environment variable while any other thread is concurrently modifying any environment variable. A call to any function dependent on any environment variable shall be considered a use of the environ variable to access that environment variable.

Peter Brett and I chatted earlier today about how the situation could potentially be improved via changes to POSIX. The approach we discussed is:

  1. Provide a RCU-based alternative to the environ variable. This would suffice to enable thread-safe concurrent read and write access to the environment block via RCU handles.
  2. Update getenv(), putenv(), setenv(), and unsetenv() to operate on the RCU-based interface.
  3. When a RCU update occurs, the environ variable is set to point to the updated environment.
  4. Perhaps deprecate the environ variable.

Any concurrent use of environ or the envp pointer passed to main() with the RCU-based interface would remain undefined behavior.

Obviously, this would be a lot of work and would take a long time.