Retry sendfile on EAGAIN or EBUSY

Addresses bug 954430

The sendfile call is redriven after a blocking select()
to ensure the socket is now writeable.

Change-Id: I68242c76593405f78e30324c2913cead63463c77
This commit is contained in:
Eoghan Glynn 2012-03-14 12:31:03 +00:00
parent 1615a1fc57
commit 51a06aab1c

View File

@ -25,6 +25,7 @@ import functools
import httplib
import logging
import os
import select
import urllib
import urlparse
@ -129,10 +130,23 @@ class SendFileIterator:
return self.len
while self.sending:
sent = sendfile.sendfile(self.connection.sock.fileno(),
self.body.fileno(),
self.offset,
CHUNKSIZE)
try:
sent = sendfile.sendfile(self.connection.sock.fileno(),
self.body.fileno(),
self.offset,
CHUNKSIZE)
except OSError as e:
# suprisingly, sendfile may fail transiently instead of
# blocking, in which case we select on the socket in order
# to wait on its return to a writeable state before resuming
# the send loop
if e.errno in (errno.EAGAIN, errno.EBUSY):
wlist = [self.connection.sock.fileno()]
rfds, wfds, efds = select.select([], wlist, [])
if wfds:
continue
raise
self.sending = (sent != 0)
self.offset += sent
yield OfLength(sent)