как установить close-on-exec по умолчанию - PullRequest
17 голосов
/ 29 октября 2009

Я реализую библиотеку для запуска команд. Библиотека на C, в Linux.

В настоящее время он вызывает popen () для запуска команды и получения выходных данных. Проблема в том, что команда наследует все открытые в настоящее время обработчики файлов.

Если бы я сделал fork / exec, я мог бы явно закрыть обработчики в child. Но это означает повторную реализацию popen ().

Могу ли я установить close-on-exec на всех обработчиках, не просматривая их по очереди?

Могу ли я установить close-on-exec по умолчанию для процесса?

Спасибо!

Ответы [ 2 ]

27 голосов
/ 29 октября 2009

Нет и нет.

Вам просто нужно быть осторожным и устанавливать close-on-exec для всех файловых дескрипторов, которые вам нужны.

Установить это легко, хотя:

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

Если вы используете ядро ​​Linux & ge; 2.6.23 и glibc & ge; 2.7, open (наряду с другими аналогичными системными вызовами) принимает новый флаг O_CLOEXEC:

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

Если вы используете ядро ​​Linux & ge; 2.6.24 и glibc & ge; 2.7, fcntl принимает новый аргумент F_DUPFD_CLOEXEC:

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

Если вы используете ядро ​​Linux & ge; 2.6.27 и glibc & ge; 2.9, появляются новые системные вызовы pipe2, dup3 и т. Д., И многие другие системные вызовы получают новые флаги *_CLOEXEC:

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

Обратите внимание, что POSIX указывает , что

Функция popen () должна гарантировать, что все потоки из предыдущих вызовов popen () , которые остаются открытыми в родительском процессе, будут закрыты в новом дочернем процессе.

так что, если вы беспокоитесь о , что утечка, не беспокойтесь.

0 голосов
/ 24 апреля 2012

Старый вопрос, но как насчет использования getpid() в child после fork(), затем посмотрите в каталог /proc/PID/fd/ и просто закройте все дескрипторы, которые вы там найдете (кроме 0, 1, 2 и того, который вы получили от opendir()), а затем execve()?

...