how to set close-on-exec by default

c, exec, fork, linux

Solution

No and no.

You simply need to be careful and set close-on-exec on all file descriptors you care about.

Setting it is easy, though:

#include <fcntl.h>
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);

#include <unistd.h>
/* please don't do this */
for (i = getdtablesize(); i --> 3;) {
    if ((flags = fcntl(i, F_GETFD)) != -1)
        fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
}

If you are running Linux kernel ≥2.6.23 and glibc ≥2.7, `open` (along with other similar syscalls) accepts a new flag `O_CLOEXEC`:

#include <unistd.h>
fd = open("...", ... | O_CLOEXEC);

If you are running Linux kernel ≥2.6.24 and glibc ≥2.7, `fcntl` accepts a new argument `F_DUPFD_CLOEXEC`:

#include <fcntl.h>
newfd = fcntl(oldfd, F_DUPFD_CLOEXEC);

If you are running Linux kernel ≥2.6.27 and glibc ≥2.9, there are new syscalls `pipe2`, `dup3`, etc., and many more syscalls gain new `*_CLOEXEC` flags:

#define _GNU_SOURCE
#include <unistd.h>
pipe2(pipefds, O_CLOEXEC);
dup3(oldfd, newfd, O_CLOEXEC);

Note that POSIX specifies that

The popen() function shall ensure that any streams from previous popen() calls that remain open in the parent process are closed in the new child process.

so if you're worried about that leak, don't be.

Problem

I'm implementing a library to run commands. The library is C, on Linux. It currently does a popen() call to run a command and get output. The problem is that the command inherits all currently open file handlers. If I did a fork/exec I could close the handlers in child explicitly. But that means re-implementing popen(). Can I set close-on-exec on all handlers without looping through them one by one? Can I set close-on-exec as default for the process? Thanks!

Original source