Skip to content

Commit bb23105

Browse files
[PR #8283/54e13b0a backport][3.9] Fix blocking I/O in the event loop while processing files in a post request (#8293)
Co-authored-by: J. Nick Koston <[email protected]>
1 parent 3f79241 commit bb23105

File tree

3 files changed

+17
-6
lines changed

3 files changed

+17
-6
lines changed

CHANGES/8283.bugfix.rst

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed blocking I/O in the event loop while processing files in a POST request
2+
-- by :user:`bdraco`.

aiohttp/test_utils.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -594,8 +594,15 @@ def make_mocked_request(
594594
"""
595595
task = mock.Mock()
596596
if loop is ...:
597-
loop = mock.Mock()
598-
loop.create_future.return_value = ()
597+
# no loop passed, try to get the current one if
598+
# its is running as we need a real loop to create
599+
# executor jobs to be able to do testing
600+
# with a real executor
601+
try:
602+
loop = asyncio.get_running_loop()
603+
except RuntimeError:
604+
loop = mock.Mock()
605+
loop.create_future.return_value = ()
599606

600607
if version < HttpVersion(1, 1):
601608
closing = True

aiohttp/web_request.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -726,19 +726,21 @@ async def post(self) -> "MultiDictProxy[Union[str, bytes, FileField]]":
726726
# https://tools.ietf.org/html/rfc7578#section-4.4
727727
if field.filename:
728728
# store file in temp file
729-
tmp = tempfile.TemporaryFile()
729+
tmp = await self._loop.run_in_executor(
730+
None, tempfile.TemporaryFile
731+
)
730732
chunk = await field.read_chunk(size=2**16)
731733
while chunk:
732734
chunk = field.decode(chunk)
733-
tmp.write(chunk)
735+
await self._loop.run_in_executor(None, tmp.write, chunk)
734736
size += len(chunk)
735737
if 0 < max_size < size:
736-
tmp.close()
738+
await self._loop.run_in_executor(None, tmp.close)
737739
raise HTTPRequestEntityTooLarge(
738740
max_size=max_size, actual_size=size
739741
)
740742
chunk = await field.read_chunk(size=2**16)
741-
tmp.seek(0)
743+
await self._loop.run_in_executor(None, tmp.seek, 0)
742744

743745
if field_ct is None:
744746
field_ct = "application/octet-stream"

0 commit comments

Comments
 (0)