Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> Libraries can (and do) spawn threads before main

I don't think any library should be calling setenv(), there's always a better way. If you know of a counterexample, please share it, I'd like to see it.

> Just remember to do it before fork() and not between fork() and exec() because you probably want to copy the existing envp and allocators usually aren't async signal safe.

Why would you go to all that trouble? Most implementations just use the stack to build the arguments for execve(), making all that irrelevant.

> If you want to be sure to be correct, use posix_spawn to create a child process.

That's not the purpose of posix_spawn(), it exists to deal with vfork-only nommu architectures:

>> [posix_spawn() was] specified by POSIX to provide a standardized method of creating new processes on machines that lack the capability to support the fork(2) system call.

>> These functions are not meant to replace the fork(2) and execve(2) system calls. In fact, they provide only a subset of the functionality that can be achieved by using the system calls.

Anyway... back to our regularly scheduled programming:

> the POSIX specification for setenv guarantees it to be buggy in most programs that think they should be using it. [...] POSIX is full of shit like this, and "you should know better" isn't a good enough excuse.

I completely disagree.

The C standard library is chock full of non-reentrant APIs. Nobody who has read more than ten manpages would reasonably assume that anything is reentrant without an explicit assurance. Locks are trivial. POSIX expects you to use a lock if you want to use setenv() like this.

I also want to point out that (at least on Linux) getenv() returns a pointer to the stack! How could anybody with basic programming literacy reasonably expect that to be thread safe? It's exactly analogous to getopt() and argv.

No, the authors obviously couldn't imagine that $FAANG would be building 4GB binaries with 1000+ recursive library dependencies, each of which has its own chance to reenact the printer scene from Officespace with your shared envp. I think that's an organizational problem, not a POSIX problem.

I'm not saying the standard shouldn't change: I would love to see argv and envp become immutable. If we're going to change it, that's the right move IMHO. But I don't really think that's practical...

> It's like saying "hey you should have known unless you press the doohickey for 5 seconds and turn the chainsaw at 90 degrees when you start it, the chain is going to fly off."

I think it's more like saying "we can't stop people from getting hurt jaywalking, so we're going to solve the problem by legally requiring everybody to wear helmets at all times outdoors".



> I don't think any library should be calling setenv()

It’s already a problem if the library is calling getenv(), because this could happen concurrently to the main program calling setenv(). The only universally safe solution is to not use setenv()/putenv() at all.

Which I think is actually reasonable. But yes it makes those functions broken in a multithreaded program.


>I also want to point out that (at least on Linux) getenv() returns a pointer to the stack! How could anybody with basic programming literacy reasonably expect that to be thread safe?

getenv_r is the standard way to provide thread safety in such situations: https://man.netbsd.org/getenv.3




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: