until_no_eintr correct?

Martin Pool mbp at canonical.com
Mon Dec 14 02:10:44 GMT 2009


2009/12/13 John Arbash Meinel <john at arbash-meinel.com>:
> I've been digging through some of the networking code, and I've seen a
> lot of code that looks like this:
>
> SmartServerPipeStreamMedium._write_out(bytes):
>        osutils.until_no_eintr(self._out.write, bytes)
>
> Which looks like it will catch EINTR and keep trying to call write(bytes).
>
> However, wouldn't we have already written some of those bytes to the
> file when EINTR comes along? For example, imagine you are writing 40MB
> to the ssh file handle, to send it across the network to the caller. If
> you wrote 5MB and then got EINTR, wouldn't the call start over at the
> beginning and re-write those first 5MB?

That case can happen, but you don't get EINTR.   Instead, the write(2)
call returns 5<<20.  As well as handling eintr, we need to handle
short writes.

This is done by Python's socket.sendall which osutils.send_all calls,
but we should be careful to do it correctly if we're write()ing by
hand.

SmartServerPipeStreamMedium does indeed seem to have this bug.

until_no_eintr is in a sense a dangerous function because it
encourages you to solve just half the problem.  Perhaps we should
deprecate it in favour of things that really do read or write all the
requested data.

> Or is EINTR something that can only happen as an all-or-nothing. So if
> you get EINTR none of the bytes have been written yet.

Correct.

The different cases are more obvious for read - if you imagine asking
to read 100 bytes:

0 = end of file
-1, eintr = interrupted by a signal, try again
20 = got 20 bytes, here they are, if you try again you could get any
of these results
100 = got 100 bytes, and there might be more or there might not be

eintr in a sense 'really' exists to distinguish 'nothing read yet'
from 'nothing more to read'.

Similarly for EAGAIN/EWOULDBLOCK if that is turned on for this socket.

-- 
Martin <http://launchpad.net/~mbp/>



More information about the bazaar mailing list