Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c

sockets

epoll

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?

like image 972
lazyconfabulator Avatar asked Sep 09 '10 04:09

lazyconfabulator


People also ask

How do you set a non-blocking socket?

To mark a socket as non-blocking, we use the fcntl system call. Here's an example: int flags = guard(fcntl(socket_fd, F_GETFL), "could not get file flags"); guard(fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK), "could not set file flags"); Here's a complete example.

What happens with a write on a blocking socket if the socket buffer is full?

It will block once your side's buffers are full enough.

What are the differences between blocking and non-blocking sockets why would you use one or the other?

In blocking socket mode, a system call event halts the execution until an appropriate reply has been received. In non-blocking sockets, it continues to execute even if the system call has been invoked and deals with its reply appropriately later.


1 Answers

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!

like image 145
Alex Martelli Avatar answered Sep 23 '22 03:09

Alex Martelli