Да, по умолчанию всякий раз, когда вы запускаете процесс (что делает system
), дочерний объект наследует все файловые дескрипторы родителя. Если ребенку не нужны эти дескрипторы, он ДОЛЖЕН их закрыть. Способ сделать это с помощью system
(или любого другого метода, который выполняет fork + exec) - установить флаг FD_CLOEXEC для всех файловых дескрипторов, которые не должны использоваться дочерними элементами вашего процесса. Это заставит их автоматически закрываться всякий раз, когда какой-либо дочерний элемент исполняет какую-либо другую программу.
Как правило, в ЛЮБОЕ ВРЕМЯ ваша программа открывает ЛЮБОЙ ВИД дескриптора файла, который будет существовать в течение длительного периода времени (например, сокета прослушивания в вашем примере), и который не должен передаваться детям, вы должны сделать
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
в дескрипторе файла.
По состоянию на 2016 год? В версии POSIX.1 вы можете использовать флаг SOCK_CLOEXEC
или тип сокета, чтобы автоматически получить это поведение при создании сокета:
listenfd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, 0);
bind(listenfd, ...
listen(listemfd, ...
который гарантирует, что он будет закрыт должным образом, даже если какой-то другой одновременно запущенный поток выполняет вызов system
или fork
+ exec
. К счастью, этот флаг уже некоторое время поддерживается в Unix-системах Linux и BSD (но, к сожалению, не в OSX).