non-blocking IO EAGAIN on write

Roy Smith roy at panix.com
Sat Jul 24 07:25:09 EDT 2010


In article <mailman.1105.1279945954.1673.python-list at python.org>,
 Kushal Kumaran <kushal.kumaran+python at gmail.com> wrote:

> In general, after select has told you a descriptor is ready, the 
> first write after that should always succeed.

I used to think that too.  Over the last few years, I've been 
maintaining a large hunk of cross-platform C++ code which makes heavy 
use of select(), with both UDP and TCP sockets.  I've seen lots of 
strange behavior.

For the moment, assume we're talking about a single-threaded program.  
This simplifies things a lot.

If you write (pseudo-code):

select(fd)
write(fd)

when the select indicates fd is ready, it's not really saying, "The 
following i/o call will succeed".  What it's saying is, "The following 
i/o call won't block".  It could return an error, as long as it returns 
it immediately.

Consider, for example, a write on a TCP connection.  You are sitting in 
a select(), when the other side closes the connection.  The select() 
should return, and the write should then immediately fail.  If you're 
tempted to say that the select() should return some sort of error, 
consider the case where the remote end closes the connection after the 
select() returns but before your process gets to execute the following 
write() call.

We also saw a case where (due to what we consider a kernel bug), a 
received UDP packet with a checksum error would cause the select() to 
wake up, *then* notice the checksum error and discard the packet, and 
thus the following read() would block.

The bottom line is if you really want to make sure you never block in an 
I/O call, put your descriptor into non-blocking mode, and treat select() 
as a *hint*.  A way to ask the kernel, "Tell me when you think it might 
be a good idea to try polling this descriptor again".



More information about the Python-list mailing list