如何在不继承句柄的情况下分叉进程?

4

在我的C/C++服务器应用程序中,它运行于Mac操作系统(Darwin Kernel Version 10.4.0),我要分叉子进程,并希望这些子进程不继承服务器的文件句柄(文件、套接字、管道等)。似乎默认情况下所有句柄都会被继承,甚至netstat显示子进程正在侦听服务器的端口。如何进行此类分叉操作?


2
如果在fork()之后执行exec(),也许这个答案会对你有所帮助:https://dev59.com/z3I-5IYBdhLWcg3w18Z3#1644590 - Olaf Dietsche
3个回答

11
通常,在调用exec()之前,需要先调用fork(),并使用getrlimit(RLIMIT_NOFILE, fds);获取文件描述符的数量,然后关闭所有低于fds的文件描述符。

此外,可以通过使用fcntl()在文件描述符上设置close-on-exec,以使它们在exec()时自动关闭。但是,这种方式不是线程安全的,因为另一个线程可能会在该线程打开新文件描述符后但在设置close-on-exec标志之前调用fork()

在Linux上,通过向open()等函数添加O_CLOEXEC标志来解决了这个问题,因此不需要额外的调用来设置close-on-exec标志。


如果你要执行 exec,你可以配置所有的FDs为“在执行时关闭”。但是我认为OP不打算执行任何东西... - Kerrek SB
@KerrekSB 是的,但人们仍然可能希望执行关闭循环,以确保没有文件描述符泄漏到新进程中,因为在某个地方设置了“close-on-exec”被忽略了。 - Maxim Egorushkin
@KerrekSB 如果您调用第三方API甚至一些操作系统函数,则可能无法控制其中任何一个开放或分支。 - pilkch

2
不需要,因为只有你知道哪些需要保持打开状态,所以你需要自己关闭它们。

我不想保留它们中的任何一个。在 fork 后有没有一些方法可以获取子进程中所有句柄? - Mihran Hovsepyan
2
嗯,你可以只使用 for (i=0; i < 1024; ++i) close(i); 这个方法,或者如果你有很多连接的话,可以选择更高的数字。 (或者最好像 @Maxim 一样使用 getrlimit(RLIMIT_NOFILE, fds); 来获取你可以拥有的最高 fd) - hexist

0

基本上不行。你必须自己完成。也许pthread_atfork可以帮助,但仍然会很繁琐。


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