Skip to content

Unhandled BrokenPipeError in asyncio.streams #104340

Closed
@TheTechromancer

Description

@TheTechromancer

Bug report

Kind of a weird one here, been running into it a for a while but just recently figured out how to reproduce it reliably.

Basically, if an async process is killed while a large amount of data remains to be written to its stdin, it fails to throw a ConnectionResetError and instead experiences a BrokenPipeError inside the _drain_helper() method. Because the exception happens inside an internal task, it evades handling by the user.

Traceback (most recent call last): File "/brokenpipeerror_bug.py", line 28, in main await proc.stdin.drain() File "/usr/lib/python3.10/asyncio/streams.py", line 371, in drain await self._protocol._drain_helper() File "/usr/lib/python3.10/asyncio/streams.py", line 173, in _drain_helper await waiter BrokenPipeError

Minimal reproducible example:

import asyncio import traceback async def main(): proc = await asyncio.create_subprocess_exec("sleep", "999", stdin=asyncio.subprocess.PIPE) try: for _ in range(10000): # NOTE: only triggers if this is a high number i = b"www.blacklanternsecurity.com\n" proc.stdin.write(i) proc.kill() await proc.stdin.drain() # This triggers error except BrokenPipeError: print(f"Handled error: {traceback.format_exc()}") asyncio.run(main())

$ python brokenpipeerror_bug.py Handled error: Traceback (most recent call last): File "/brokenpipeerror_bug.py", line 28, in main await proc.stdin.drain() File "/usr/lib/python3.10/asyncio/streams.py", line 371, in drain await self._protocol._drain_helper() File "/usr/lib/python3.10/asyncio/streams.py", line 173, in _drain_helper await waiter BrokenPipeError Future exception was never retrieved future: <Future finished exception=BrokenPipeError()> Traceback (most recent call last): File "/brokenpipeerror_bug.py", line 28, in main await proc.stdin.drain() File "/usr/lib/python3.10/asyncio/streams.py", line 371, in drain await self._protocol._drain_helper() File "/usr/lib/python3.10/asyncio/streams.py", line 173, in _drain_helper await waiter BrokenPipeError

Tested on CPython 3.10.10 on Arch Linux, x86_64

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions