Unverified Kaydet (Commit) 7165754b authored tarafından Yury Selivanov's avatar Yury Selivanov Kaydeden (comit) GitHub

bpo-32410: Avoid blocking on file IO in sendfile fallback code (GH-7172)

üst 416c1ebd
...@@ -800,7 +800,10 @@ class BaseEventLoop(events.AbstractEventLoop): ...@@ -800,7 +800,10 @@ class BaseEventLoop(events.AbstractEventLoop):
async def _sock_sendfile_fallback(self, sock, file, offset, count): async def _sock_sendfile_fallback(self, sock, file, offset, count):
if offset: if offset:
file.seek(offset) file.seek(offset)
blocksize = min(count, 16384) if count else 16384 blocksize = (
min(count, constants.SENDFILE_FALLBACK_READBUFFER_SIZE)
if count else constants.SENDFILE_FALLBACK_READBUFFER_SIZE
)
buf = bytearray(blocksize) buf = bytearray(blocksize)
total_sent = 0 total_sent = 0
try: try:
...@@ -810,7 +813,7 @@ class BaseEventLoop(events.AbstractEventLoop): ...@@ -810,7 +813,7 @@ class BaseEventLoop(events.AbstractEventLoop):
if blocksize <= 0: if blocksize <= 0:
break break
view = memoryview(buf)[:blocksize] view = memoryview(buf)[:blocksize]
read = file.readinto(view) read = await self.run_in_executor(None, file.readinto, view)
if not read: if not read:
break # EOF break # EOF
await self.sock_sendall(sock, view) await self.sock_sendall(sock, view)
......
...@@ -14,6 +14,10 @@ DEBUG_STACK_DEPTH = 10 ...@@ -14,6 +14,10 @@ DEBUG_STACK_DEPTH = 10
# Number of seconds to wait for SSL handshake to complete # Number of seconds to wait for SSL handshake to complete
SSL_HANDSHAKE_TIMEOUT = 10.0 SSL_HANDSHAKE_TIMEOUT = 10.0
# Used in sendfile fallback code. We use fallback for platforms
# that don't support sendfile, or for TLS connections.
SENDFILE_FALLBACK_READBUFFER_SIZE = 1024 * 256
# The enum should be here to break circular dependencies between # The enum should be here to break circular dependencies between
# base_events and sslproto # base_events and sslproto
class _SendfileMode(enum.Enum): class _SendfileMode(enum.Enum):
......
...@@ -1818,12 +1818,15 @@ class BaseLoopSockSendfileTests(test_utils.TestCase): ...@@ -1818,12 +1818,15 @@ class BaseLoopSockSendfileTests(test_utils.TestCase):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
cls.__old_bufsize = constants.SENDFILE_FALLBACK_READBUFFER_SIZE
constants.SENDFILE_FALLBACK_READBUFFER_SIZE = 1024 * 16
with open(support.TESTFN, 'wb') as fp: with open(support.TESTFN, 'wb') as fp:
fp.write(cls.DATA) fp.write(cls.DATA)
super().setUpClass() super().setUpClass()
@classmethod @classmethod
def tearDownClass(cls): def tearDownClass(cls):
constants.SENDFILE_FALLBACK_READBUFFER_SIZE = cls.__old_bufsize
support.unlink(support.TESTFN) support.unlink(support.TESTFN)
super().tearDownClass() super().tearDownClass()
......
...@@ -2160,6 +2160,17 @@ class SockSendfileMixin(SendfileBase): ...@@ -2160,6 +2160,17 @@ class SockSendfileMixin(SendfileBase):
async def wait_closed(self): async def wait_closed(self):
await self.fut await self.fut
@classmethod
def setUpClass(cls):
cls.__old_bufsize = constants.SENDFILE_FALLBACK_READBUFFER_SIZE
constants.SENDFILE_FALLBACK_READBUFFER_SIZE = 1024 * 16
super().setUpClass()
@classmethod
def tearDownClass(cls):
constants.SENDFILE_FALLBACK_READBUFFER_SIZE = cls.__old_bufsize
super().tearDownClass()
def set_socket_opts(self, sock): def set_socket_opts(self, sock):
# On macOS, SO_SNDBUF is reset by connect(). So this method # On macOS, SO_SNDBUF is reset by connect(). So this method
# should be called after the socket is connected. # should be called after the socket is connected.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment