== _fork()_ and closing file descriptors As I noted in [[Why _fork()_ is a good API ForkGoodAPI]], back in the bad old days Unix had a problem of stray file descriptors leaking from processes into commands that they ran (for example, _rsh_ used to gift your shell process with any number of strays). In theory the obvious way to solve this is to have code explicitly close all file descriptors before it _exec()_s something. In practice Unix has chosen to solve this with a special flag on file descriptors, ((FD_CLOEXEC)), which causes them to be automatically closed when the process _exec()_s. In [[that entry ForkGoodAPI]] I mentioned that there was a good reason for this alternate solution in practice. At the start of planning this followup entry I had a nice story all put together in my head about why this was so, involving thread-based concurrency races. Unfortunately that story is wrong (although a closely related concurrency race story is the reason for things like ((O_CLOEXEC)) in [[Linux's _open()_ http://www.kernel.org/doc/man-pages/online/pages/man2/open.2.html]]). ((FD_CLOEXEC)) is not necessary to deal with a concurrency race between thread A creating a new file descriptor and thread B _fork()_ing and then _exec()_ing in the child process, because the child's file descriptors are frozen at the moment that it's created by _fork()_ (with a standard _fork()_). It's perfectly safe for the child process to manually close all stray open file descriptors in user-level code, because no matter what it does thread A can never make new file descriptors appear in the child process partway through this. Either they're there at the start (and will get closed by the user-level code), or they'll never be there at all. There are, however, several practical reasons that ((FD_CLOEXEC)) exists. First and foremost, it proved pragmatically easier to get code (often library code) to set ((FD_CLOEXEC)) than to get every bit of code that did a _fork()_ and _exec()_ sequence to always clean up file descriptors properly. It also means that you don't have to worry about file descriptors being created in the child process in various ways, especially by library code (which might be threaded code, for extra fun). Finally, it deals with the problem that Unix has no API for finding out what file descriptors your process has open, so your only way of closing all stray file descriptors in user code is the brute force approach of looping trying to close each one in turn (and on modern Unixes, that can be a lot of potential file descriptors). Once you have ((FD_CLOEXEC)) and programs that assume they can use it to just _fork()_ and _exec()_, you have the thread races that lead you to needing things like ((O_CLOEXEC)). Any time a file descriptor can come into existence without ((FD_CLOEXEC)) being set on it, you have a race between thread A creating the file descriptor and then setting ((FD_CLOEXEC)) and thread B doing a _fork()_ and _exec()_. If thread B 'wins' this race, it will inherit a new file descriptor that does *not* have ((FD_CLOEXEC)) set and this file descriptor will leak through the _exec()_. (All of this is well known in the Unix programming community that pays attention to this stuff. I'm writing it down here so that I can get it straight and firmly fixed into my head, since I almost made an embarrassing mistake about it.)