Launch a child process on OSX/Unix that doesn'

2020-06-23 07:50发布

问题:

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!

回答1:

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



回答2:

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 Getting the highest allocated file descriptor for some additional details, including approaches for other systems.



回答3:

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.



回答4:

@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!