views:

353

answers:

4

I want to launch a child process on OS X such that the child process does not inherit the current process's open files/ports.

Any suggestions on how to accomplish this? Shell commands that I can invoke using the system() function would work too - I just don't know of a good shell command that enables this.

Thanks!

+8  A: 

You didn't specify what language you are developing in, but since you mentioned system(), I assume you mean C or C++.

Typically this is accomplished by using fcntl() to set the close-on-exec flag on those file descriptors that you do not want to be inherited:

int fd = open("somefile", O_RDONLY);
fcntl(fd, F_SETFD, FD_CLOEXEC);

You could also do it the brute force way by iterating through all possible fd's in the child process after you fork but before you exec. This is a bit trickier because it requires that you know what the maximum possible fd value is, and it is also less efficient because you'll end up iterating through and "closing" a bunch of unused fd's. Something like this:

pid_t pid = fork();
switch (pid) {
    case 0:
        // In the child process.  Iterate through all possible file descriptors
        // and explicitly close them.

        long maxfd = sysconf(OPEN_MAX);
        for (long i = 0; i < maxfd; ++i) {
            close(i);
        }

        // Now exec the new program, file-handle free.

        execlp("someprogram", "arg1", "arg2");
        break;
    case -1:
        // TODO: handle errors.

        break;
    default:
        // Parent process.

        int status;
        pid_t finished = waitpid(pid, &status, 0);
        break;
}

Hope that helps,

Eric Melski

Eric Melski
+1  A: 

On Mac OS X you can use read the directory /dev/fd/ with opendir()/readdir() to determine the set of open file descriptors. With this information you can either call fcntl(fd, F_SETFD, FD_CLOEXEC) on each open file descriptor, or alternatively you could call close(fd) on each file descriptor after forking.

See http://stackoverflow.com/questions/899038/getting-the-highest-allocated-file-descriptor/918469#918469 for some additional details, including approaches for other systems.

mark4o
A: 

After some experimenting, I found that the 'open' shell command on Mac creates a process that does not inherit the parents files/ports. Invoking 'open foo.app' as arguments to the system function does the trick. Of course, this is mac only. For Unix, one of the other approaches suggested here makes a lot of sense.

psychotik
The open command tells launchd to spawn the process (or open the document in an existing process), so you are not its parent. That is why it will not inherit anything from you.
mark4o
A: 

@Eric M: Your answer got me most of the way there, but I found that it still left some file descriptors open. I replaced sysconf(OPEN_MAX) in your code above with getdtablesize() and it works great. Thanks for the help!

escouten