使用accept4()函数设置SOCK_CLOEXEC标志的目的是什么,与O_CLOEXEC相同吗?

11

基本上,我需要知道在使用accept4()函数时,设置SOCK_CLOEXEC的目的是什么。 我如何通过从accept返回的文件描述符检查此标志的功能。

accepted_fd =   accept4(sd, (struct sockaddr *)& tcp_remote, &size,  SOCK_CLOEXEC);
1个回答

14
< p> SOCK_CLOEXEC 的存在是为了避免在从 accept 获取新套接字并在之后设置FD_CLOEXEC 标志之间发生竞态条件。

通常,如果您希望文件描述符在执行时关闭,则应首先以某种方式获取文件描述符,然后调用fcntl(fd,F_SETFD,FD_CLOEXEC)。但在多线程程序中,有可能在获取该文件描述符(在此情况下来自accept )和设置CLOEXEC标志之间发生竞争条件。因此,Linux最近已更改了大多数(如果不是全部)返回新文件描述符的系统调用,以便接受指示内核在使文件描述符有效之前原子地设置close-on-exec标志的标志。这样,竞争条件就被解决了。

如果您想知道为什么需要exec时关闭文件,那是因为在某些情况下,特别是在从特权程序执行非特权程序时,您不希望一些文件描述符泄漏到该程序中。


4
我不会把O_CLOEXEC描述为主要用于特权升级/安全原因 - 如果一个FD在它预期关闭的时间之后仍然保持打开状态,因为子进程仍然拥有它,那么发生非安全性错误(通常是无限阻塞类型)也是非常普遍的。 - Charles Duffy
2
如果他们没有处理不同特权级别的进程,鼓励人们认为“哦,这不是我需要担心的事情”是没有帮助的。 - Charles Duffy
我个人遇到过很多这样的问题——主要是在专有代码库中,否则我会向您指出错误报告和补丁。考虑一下生成通过一对管道连接的子进程的正常过程,在其中写入数据,关闭出站管道,在入站管道中读取数据,并在完成后等待其退出(wait()ing)。如果在关闭出站管道之前生成了子进程,并且该子进程无限期地保持FD打开状态,则可能会陷入一个情况,即该进程将永远无法完成读取,从而永远不能退出。 - Charles Duffy
是的,问题就在于最后关闭实际上关闭了,但是这是一个大问题。 :) - Charles Duffy
谢谢大家的回答,但请问你们能否提供一种测试已设置SOCK_CLOEXEC的FD的方法?我可以通过设置SOCK_NOBLOCK来测试由accept4返回的FD的功能...但我需要看看SOCK_CLOEXEC是如何工作的...因为我之前没有处理过这个问题,我尝试了fork但它不能工作!我不知道如何使用exec()或任何基本功能来检查它。 - Hatem Mashaqi
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接