FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

gh-103847: fix some asyncio subprocess cancellation bugs by kumaraditya303 · Pull Request #146571 · python/cpython · GitHub

Repository navigation

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .py  (4) All 1 file type selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
18 changes: 15 additions & 3 deletions Lib/asyncio/base_subprocess.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def __init__(self, loop, protocol, args, shell,
self._proc = None
self._pid = None
self._returncode = None
self._exit_waiters = []
self._exit_waiters = set()
self._pending_calls = collections.deque()
self._pipes = {}
self._finished = False
Expand Down Expand Up @@ -211,6 +211,14 @@ async def _connect_pipes(self, waiter):
except (SystemExit, KeyboardInterrupt):
raise
except BaseException as exc:
# Close any pipes that were already connected before the
# error/cancellation to avoid leaking file descriptors.
for proto in self._pipes.values():
if proto is not None:
proto.pipe.close()
for raw_pipe in (proc.stdin, proc.stdout, proc.stderr):
if raw_pipe is not None:
raw_pipe.close()
if waiter is not None and not waiter.cancelled():
waiter.set_exception(exc)
else:
Expand Down Expand Up @@ -260,8 +268,12 @@ async def _wait(self):
return self._returncode

waiter = self._loop.create_future()
self._exit_waiters.append(waiter)
return await waiter
self._exit_waiters.add(waiter)
try:
return await waiter
finally:
if self._exit_waiters is not None:
self._exit_waiters.discard(waiter)

def _try_finish(self):
assert not self._finished
Expand Down
2 changes: 1 addition & 1 deletion Lib/asyncio/unix_events.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ async def _make_subprocess_transport(self, protocol, args, shell,
raise
except BaseException:
transp.close()
await transp._wait()
await tasks.shield(transp._wait())
raise

return transp
Expand Down
2 changes: 1 addition & 1 deletion Lib/asyncio/windows_events.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ async def _make_subprocess_transport(self, protocol, args, shell,
raise
except BaseException:
transp.close()
await transp._wait()
await tasks.shield(transp._wait())
raise

return transp
Expand Down
5 changes: 1 addition & 4 deletions Lib/test/test_asyncio/test_subprocess.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from asyncio import subprocess
from test.test_asyncio import utils as test_utils
from test import support
from test.support import os_helper, warnings_helper, gc_collect
from test.support import os_helper, gc_collect

if not support.has_subprocess_support:
raise unittest.SkipTest("test module requires subprocess")
Expand Down Expand Up @@ -1028,7 +1028,6 @@ async def main():

self.loop.run_until_complete(main())

@warnings_helper.ignore_warnings(category=ResourceWarning)
def test_subprocess_read_pipe_cancelled(self):
async def main():
loop = asyncio.get_running_loop()
Expand All @@ -1039,7 +1038,6 @@ async def main():
asyncio.run(main())
gc_collect()

@warnings_helper.ignore_warnings(category=ResourceWarning)
def test_subprocess_write_pipe_cancelled(self):
async def main():
loop = asyncio.get_running_loop()
Expand All @@ -1050,7 +1048,6 @@ async def main():
asyncio.run(main())
gc_collect()

@warnings_helper.ignore_warnings(category=ResourceWarning)
def test_subprocess_read_write_pipe_cancelled(self):
async def main():
loop = asyncio.get_running_loop()
Expand Down
Loading

Back | FazBrowse Home | New Git URL