坏文件描述符关闭Boost套接字

时间:2011-10-11 21:27:12

标签: c++ boost boost-asio

我正在使用Boost 1.45 ASIO来处理在Windows和Mac上运行的应用程序中的某些套接字连接。在Windows上,以下代码不会导致任何错误,我的套接字将完全关闭。在Mac上,关闭和(如果我注释掉)关闭函数都会给我“错误的文件描述符”错误。直到我调用此代码,套接字工作正常。但是一旦我调用shutdown或close,我就会收到错误。可能会发生什么想法?

if(socket.is_open())
{
    socket.shutdown(socket.both);
    socket.close();
}

3 个答案:

答案 0 :(得分:7)

close上的“错误文件描述符”通常意味着描述符已经关闭。这通常是因为程序中某些完全不相关的部分存在双重错误。

这样的错误可能具有传染性。如果你的程序关闭了两次相同的描述符,并且它在过渡期间被重新分配,那么第二个close将从它们下面关闭一些不相关的对象的描述符。然后当该对象关闭其描述符时,它实际上可以关闭另一个对象的描述符......依此类推,直到最后一个对象获得“错误的文件描述符”错误。

这是(a)描述符是全局状态的副作用,以及(b)对open / socket / etc的任何调用的Unix要求。分配编号最小的未使用描述符。

我知道调试它的唯一方法是使用strace(在Linux上)或dtrace(在Mac上)等工具监视所有文件描述符的创建和销毁。 (好吧,也许不是唯一的方法。我曾经写过一个复杂的LD_PRELOAD黑客来拦截对openclose的每次调用,以找出哪个线程正在双重关闭它们的描述符,因为第二次关闭是另一个线程使用的描述符......)

祝你好运。

答案 1 :(得分:2)

if(socket.is_open())
{
    socket.shutdown(socket.both);
    socket.close();
}

除非你有充分的理由这样做,否则我建议让socket::~socket()析构函数关闭底层的本机文件描述符。如果您担心泄漏描述符,请使用valgrind之类的工具来分析您的程序。

答案 2 :(得分:0)

我有同样的问题:在Windows上一切正常,在Linux上,根据套接字状态IIRC抛出异常。

Sam的回答的替代方法是使用伪error_code在发生异常时静默忽略该异常。请参阅asio文档中的closeshutdown重载。