Запустите дочерний процесс в OSX / Unix, который не наследует файлы / порты - PullRequest
3 голосов
/ 21 августа 2009

Я хочу запустить дочерний процесс в OS X, чтобы дочерний процесс не наследовал открытые файлы / порты текущего процесса.

Есть предложения о том, как этого добиться? Команды оболочки, которые я могу вызывать с помощью функции system (), тоже будут работать - я просто не знаю хорошей команды оболочки, которая позволяет это.

Спасибо!

Ответы [ 4 ]

11 голосов
/ 21 августа 2009

Вы не указали, на каком языке вы разрабатываете, но поскольку вы упомянули system(), я предполагаю, что вы имеете в виду C или C ++.

Как правило, это достигается с помощью fcntl () для установки флага close-on-exec для тех файловых дескрипторов, которые вы не хотите наследовать:

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

Вы также можете сделать это методом грубой силы, просматривая все возможные fd в дочернем процессе после разветвления, но перед выполнением. Это немного сложнее, потому что это требует, чтобы вы знали, каково максимально возможное значение fd, и это также менее эффективно, потому что в конечном итоге вы будете повторять и «закрывать» кучу неиспользованных fd. Примерно так:

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;
}

Надеюсь, это поможет,

Эрик Мелски

1 голос
/ 21 августа 2009

В Mac OS X вы можете использовать чтение каталога /dev/fd/ с opendir() / readdir(), чтобы определить набор дескрипторов открытых файлов. Получив эту информацию, вы можете либо вызвать fcntl( fd , F_SETFD, FD_CLOEXEC) для каждого дескриптора открытого файла, либо вы можете вызвать close( fd ) для каждого дескриптора файла после разветвления .

См. Получение максимально выделенного дескриптора файла для некоторых дополнительных деталей, включая подходы для других систем.

0 голосов
/ 05 января 2010

@ Эрик М: Ваш ответ помог мне пройти большую часть пути, но я обнаружил, что некоторые файловые дескрипторы все еще остаются открытыми. Я заменил sysconf(OPEN_MAX) в вашем коде выше на getdtablesize(), и он прекрасно работает. Спасибо за помощь!

0 голосов
/ 22 августа 2009

После некоторых экспериментов я обнаружил, что команда оболочки 'open' на Mac создает процесс, который не наследует родительские файлы / порты. Вызов 'open foo.app' в качестве аргументов системной функции делает свое дело. Конечно, это только Mac. Для Unix один из других подходов, предложенных здесь, имеет большой смысл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...