如何释放多个进程之间共享的套接字描述符?

How to free socket descriptor shared between multiple processes?

背景

在 Linux 或 BSD 上,可以使用 SCM_RIGHTS 在不相关的进程之间发送打开文件或套接字的句柄,我有这个工作,这样进程正在监听连接,然后将句柄转发给执行通信的进程。

问题

我不知道如何在不关闭套接字的情况下从侦听进程中释放套接字句柄。

man close(3)中有两个相互矛盾的描述:

When all file descriptors associated with an open file description have been closed, the open file description shall be freed.

If fildes refers to a socket, close() shall cause the socket to be destroyed.

我最初认为这意味着调用 close() 只会减少具有套接字的内核对象的引用计数,因此 man close(3) 的最后描述意味着 "destroy when the last descriptor is closed" .

编辑:这是它应该如何工作,也是如何工作的。

但是,当我 运行 测试时,似乎只要我在侦听过程中对套接字描述符调用 close(),它就会开始关闭套接字,发送 RSTFIN,取决于当时其他进程对套接字执行的操作。

一种解决方案是使用 "you can now close socket nnn" 从处理过程中进行回调,但这会在侦听过程中保持打开多个套接字描述符并增加一些开销。

我知道我可以通过直接从任一进程调用 shutdown() 来强制套接字启动关闭进程,但我想 阻止 它。

我假设存在一个简单的解决方案,但我找不到。

问题

有没有办法从侦听进程中注销套接字描述符,使其不再在进程的文件描述符table中,而是没有 激活套接字关闭?

源代码

用于发送套接字的SCM_RIGHTS实现在这里(send_fdsnative_close):

发送套接字然后关闭它的代码在这里:

如果我注释掉第 497 行,一切正常,但显然会发生大量文件描述符泄漏。

SCM_RIGHTS的接收端在这里:

tl;dr: 当最后一个引用关闭时套接字也关闭。

我的问题的答案最有可能是:

No, there is no way to prevent the socket shutdown, but it is not needed as the socket will not close until the last descriptor has closed.

安德鲁的回答是正确的,让我走上正轨:这没有意义,其他人一直都是这样。

最后,问题是关闭套接字的处理程序进程超时,但这看起来像是来自侦听器的 close() 调用是问题所在。

当我停止来自监听进程的 close() 调用时,它开始工作了。发生这种情况是因为超时正确地关闭了句柄,但是仍然有一个引用(在监听过程中)所以套接字保持打开状态。