Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bad file descriptor closing Boost socket

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();
}
like image 844
Matt McMinn Avatar asked Oct 11 '11 21:10

Matt McMinn


2 Answers

"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) or dtrace (on Mac). (Well, maybe not the only way. I once wrote a convoluted LD_PRELOAD hack to intercept every call to open and close 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.

like image 91
Nemo Avatar answered Oct 09 '22 08:10

Nemo


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

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.

like image 31
Sam Miller Avatar answered Oct 09 '22 10:10

Sam Miller