如何默认设置close-on-exec

时间:2009-10-29 12:16:18

标签: c linux exec fork

我正在实现一个库来运行命令。该库是C,在Linux上。

它当前执行popen()调用来运行命令并获取输出。问题是该命令继承了所有当前打开的文件处理程序。

如果我做了一个fork / exec,我可以明确地关闭孩子的处理程序。但这意味着重新实现popen()。

我可以在所有处理程序上设置close-on-exec而不必逐个循环它们吗?

我可以将close-on-exec设置为进程的默认值吗?

谢谢!

2 个答案:

答案 0 :(得分:27)

不,不。

您只需要小心并在您关注的所有文件描述符上设置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内核≥2.6.23且glibc≥2.7,则open(以及其他类似的系统调用)会接受新标记O_CLOEXEC

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

如果您运行的Linux内核≥2.6.24且glibc≥2.7,则fcntl接受新参数F_DUPFD_CLOEXEC

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

如果您运行的Linux内核≥2.6.27且glibc≥2.9,则会有新的系统调用pipe2dup3等,还有更多的系统调用会获得新的*_CLOEXEC标志:

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

请注意POSIX specifies

  

popen()函数应确保在新的子进程中关闭在父进程中保持打开的先前 popen()调用的任何流。

所以,如果您担心 泄漏,请不要。

答案 1 :(得分:-2)

有点老问题,但如果在getpid()之后使用fork(),请查看/proc/PID/fd/目录并关闭您在那里找到的所有描述符(0,1,2和0除外)你从opendir())然后execve()获得的那个?