【问题标题】:how to set close-on-exec by default如何在默认情况下设置 close-on-exec
【发布时间】:2010-12-11 05:27:38
【问题描述】:

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

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

如果我做了一个 fork/exec,我可以显式地关闭 child 中的处理程序。但这意味着要重新实现 popen()。

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

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

谢谢!

【问题讨论】:

  • 如果您确实遍历文件描述符,请读取目录 /proc/self/fd/ 以仅处理正在使用的那些,而不是每个可能的文件描述符。

标签: c linux exec fork


【解决方案1】:

有点老问题,但是在fork() 之后的子项中使用getpid() 怎么样,然后查看/proc/PID/fd/ 目录并关闭您在其中找到的所有描述符(除了 0、1、2 和您从 @ 获得的描述符) 987654325@) 然后execve()?

【讨论】:

  • 我可能遗漏了一些东西,但在 Linux 上听起来像是一个有效的解决方法:mail.gnome.org/archives/gtk-devel-list/2015-March/msg00044.html。让我起来。
  • 这是一种完全有效的方法——事实上它通常是这样做的。不过,我会使用/proc/self/fd 进行 fds,因为它少了一步
【解决方案2】:

没有也没有。

您只需要小心并在您关心的所有文件描述符上设置 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);

注意POSIXspecifies那个

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

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

【讨论】:

  • 作为一个库,我不控制我的用户如何打开文件,所以在 open() 中使用标志不是一个选项
  • 太糟糕了,你运气不好——UNIX(和Linux)不允许你改变open等人的底层语义。你只需要忍受它,就像其他人一样。
  • 请参阅lkml.org/lkml/2004/3/29/191,了解 cloexec-by-default-switch 提案被否决的示例。这已经被提出了很多次,也被拒绝了很多次。
  • 再次向后兼容。太糟糕了,我见过很多继承文件因为松散的孩子没有退出而被卡住的情况,而且由于它是松散的,因此您无能为力。甚至不轻易杀人。手动 fork/exec 真的是构建可靠东西的唯一方法吗?
  • @Lothar socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, 0)
猜你喜欢
  • 2022-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多