我在 Mac OS XI 中遇到了一个奇怪的套接字泄漏问题,无法解释。我有一个开源守护程序 (olad),它在 9010 (tcp)、9090 (tcp) 和 6454 (udp) 以及其他端口上进行侦听。当守护进程退出时,netstat 显示端口 6454 仍处于打开状态并正在侦听:
$ netstat -f inet -n | grep 6454
<nothing>
$ olad/olad
<exit server>
$ netstat -f inet -n | grep 6454
udp4 0 0 *.6454 *.*
但是, lsof 不显示套接字:
$ lsof -i 4 -P | grep 6454
<nothing>
一旦系统处于这种状态,通过向端口发送数据包,我可以看到队列计数增加:
$ netstat -f inet -n | grep 6454
udp4 612 0 *.6454 *.*
只有在 Preferences -> Security & Privacy 中启用了应用程序防火墙并且这是第一次运行二进制文件时,才会发生这种情况。也就是说,如果我禁用防火墙,则不会发生泄漏。或者,如果启用了防火墙,在第一次运行后弹出对话框并单击接受后,问题不再出现。
一旦套接字泄漏,禁用防火墙将无法释放它。
我已经确认在程序退出之前我在所有套接字上调用 close() 并且没有调用 fork() 或新线程。
我一直在尝试缩小错误案例的范围,但它似乎是 pipe()、socket()、bind()、listen()、ioctl()、fnctl() 和 select() 之间相当复杂的交互。更改调用顺序并删除端口 9010 和 9090 上的侦听会导致问题消失。
有没有人有关于如何继续调试的建议,或者关于 Mac 应用程序防火墙如何在内部工作的指南?