1. Right after program startup before any threads are spawned.
2. After a fork before an exec.
In both cases it can be known that no threads are running. (Ok, for 1 it can actually be non-trivial if you have code before main or if you call functions that spawn helper threads, but let's assume that you can know this).
However no languages actually have ways to enforce this. So the APIs can be called at any time and are huge footguns.
I think that the proposed improvement of `getenv_s` is great. It is cheap and easy to use, then software can slowly migrate off of the less safe stuff. You can imagine that if libc stopped using `getenv` internally most of this problem would be solved.