错误的文件描述符关闭 Boost 套接字
我正在使用 Boost 1.45 ASIO 来处理在 Windows 和 Mac 上运行的应用程序中的一些套接字连接。在 Windows 上,以下代码不会导致任何错误,并且我的套接字已完全关闭。但在 Mac 上,关闭和(如果我将其注释掉)关闭函数都会给我“错误的文件描述符”错误。在我调用这段代码之前,套接字工作正常。但是一旦我调用 shutdown 或 close ,我就会收到错误。有什么想法可能会发生什么吗?
if(socket.is_open())
{
socket.shutdown(socket.both);
socket.close();
}
I'm using Boost 1.45 ASIO to handle some socket connections in an application that runs on both Windows and Mac. On Windows, the following code does not cause any errors, and my sockets are closed cleanly. On Mac though, both the shutdown and (if I comment it out) the close functions give me "Bad file descriptor" errors. Up until I call this code, the sockets work fine. But as soon as I call shutdown or close, I get the error. Any ideas what could be going on?
if(socket.is_open())
{
socket.shutdown(socket.both);
socket.close();
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
close
上的“错误文件描述符”通常意味着该描述符已被关闭。这通常是因为程序中某些完全不相关的部分存在双重关闭错误。这种错误可能具有传染性。如果您的程序两次关闭同一个描述符,并且在此期间重新分配它,则第二次
close
将从它们下面关闭一些不相关的对象的描述符。然后,当该对象关闭其描述符时,它实际上可以关闭另一个对象的描述符......依此类推,直到最后一个对象出现“错误文件描述符”错误。这是 (a) 描述符是全局状态和 (b) Unix 要求任何对 open/socket/etc 的调用的副作用。分配编号最小的未使用描述符。
我知道调试此问题的唯一方法是使用
strace
(在 Linux 上)或dtrace
(在 Mac 上)等工具来监视所有文件描述符的创建和销毁。 (好吧,也许不是唯一的方法。我曾经写过一个复杂的LD_PRELOAD
hack 来拦截对open
和close
的每次调用,以找出哪个线程双重关闭了它们的描述符,因为第二次关闭破坏了另一个线程正在使用的描述符......)祝你好运。
"Bad file descriptor" on
close
usually means the descriptor has already been closed. This is often because of a double-close bug in some completely unrelated section of the program.Such a bug can be contagious. If your program closes the same descriptor twice, and it gets re-assigned in the interim, the second
close
will close some unrelated object's descriptor out from under them. And then when that object closes its descriptor, it can actually be closing yet another object's descriptor... And so on, until the last one in line gets a "bad file descriptor" error.This is a side-effect of (a) descriptors being global state and (b) the Unix requirement that any call to open/socket/etc. assign the lowest-numbered unused descriptor.
The only way I know to debug this is to monitor the creation and destruction of all file descriptors using a tool like
strace
(on Linux) ordtrace
(on Mac). (Well, maybe not the only way. I once wrote a convolutedLD_PRELOAD
hack to intercept every call toopen
andclose
to figure out which thread was double-closing their descriptor, because the second close was nuking the descriptor being used by another thread...)Good luck.
除非您有充分的理由这样做,否则我建议让
socket::~socket()
析构函数关闭底层本机文件描述符。如果您担心描述符泄漏,请使用 valgrind 等工具来分析您的程序。Unless you have a good reason for doing this, I suggest letting the
socket::~socket()
destructor close the underlying native file descriptor. If you are concerned about leaking descriptors, use a tool like valgrind to analyze your program.我遇到了同样的问题:在 Windows 上一切正常,而在 Linux 上,根据套接字状态 IIRC 抛出异常。
Sam 的答案的另一种选择是使用虚拟 error_code 默默地忽略异常(如果确实发生)。请参阅关闭和 shutdown asio 中的重载文档。
I had the same issue: on windows everything was ok, and on linux, an exception got thrown depending on the socket state IIRC.
An alternative to Sam's answer is to use a dummy error_code to silently ignore the exception if it does occur. See the close and shutdown overloads in the asio documentation.