I have a C++ object that creates a thread to read from a blocking UDP socket:
mRunning.store(true);
while (mRunning.load(boost::memory_order_consume)) {
...
int size = recvfrom(mSocket, buf, kTextBufSize , 0,
(struct sockaddr *) &packet->mReplyAddr.mSockAddr, (socklen_t*)&packet->mReplyAddr.mSockAddrLen);
if (size > 0) {
//do stuff
}
}
return 0;
(mRunning is a boost::atomic) The object's destructor is called from another thread and does this:
mRunning.store(false);
#ifdef WIN32
if (mSocket != -1) closesocket(mSocket);
#else
if (mSocket != -1) close(mSocket);
#endif
pthread_join(mThread, NULL);
This seems to work, but one of my colleagues suggested that there might be a problem if recv is interrupted in the middle of reading something. Is this thread safe? What's the correct way of closing a blocking UDP socket? (Needs to be cross-platform OSX/Linux/Windows)
There could be a lot of different problems. Moving my application from one FreeBSD version to another I found that such close() worked normally on older kernel and just hung close() until something returned from recv() on newer. And OSX is FreeBSD based :)
Portable way of closing sockets from different thread is to create pipe and block not in recv(), but in select(). When you need to close socket, write something to pipe, select() will unblock and you can safely do close().
Well recvfrom
in itself is thread-safe. IIRC all socket functions are. The question is:
recvfrom
while it's copying data to your buffer ?It's a good question but I doubt the standard says anything about this (I also doubt the specific manual of an implementation says anything about it). So any implementation is free to:
recvfrom
fail and return a -1
(ENOTSOCK
, EINVAL
?)close
.Obviously this is just speculation (I have been wrong before, many times), but unless you find something in the standard to support the idea that you can close the socket while receiving through it, you're not safe.
So, what can you do ? THe safest: use a synchronization mechanism to ensure that you only close
the socket after the recvfrom
is done (semaphores, mutexes, whatever).
Personally I would do an UP
on a semaphore after the recvfrom
and a DOWN
before the close
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With