csocketsposixepoll

Proper handling of EWOULDBLOCK with polling on a non-blocking socket


I've been working on a polling TCP daemon for some time now. Recently, I've read that non-blocking sockets can sometimes throw an EWOULDBLOCK error during a send() or recv(). My understanding is that if recv() throws an EWOULDBLOCK, this (usually) means that there's nothing to receive. But what I'm unclear on is under what circumstances send() would throw an EWOULDBLOCK, and what would be proper procedure for handling such an event?

If send() throws an EWOULDBLOCK, should the daemon simply move on from that event, onto the next one? Using a polling interface like epoll, will a new event be fired when the descriptor becomes ready for writing?


Solution

  • what I'm unclear on is under what circumstances send() would throw an EWOULDBLOCK

    When the sending-buffer (typically held by the OS, but, anyway, somewhere in the TCP/IP stack) is full and the counterpart hasn't acknowledged any of the bits sent to it from the buffer yet (so the stack must retain everything in the buffer in case a resend is necessary).

    what would be proper procedure for handling such an event?

    In one way or another you must wait until the counterpart does acknowledge some of the packets sent to it, thereby allowing the TCP/IP stack to free some space for more "sending". Both classical select and more modern epoll (and in other OS's, kqueue &c) provide smart ways to perform such waiting (whether you're waiting to read something, write something, or "whichever of the two happens first"). Yep, watched-descriptors becoming ready (be it for reading or for writing) is the typical reason for epoll events!