mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
gh-103847: fix cancellation safety of asyncio.create_subprocess_exec (#140805)
This commit is contained in:
parent
fbebca289d
commit
ef474cfafb
3 changed files with 51 additions and 1 deletions
|
|
@ -26,6 +26,7 @@ def __init__(self, loop, protocol, args, shell,
|
|||
self._pending_calls = collections.deque()
|
||||
self._pipes = {}
|
||||
self._finished = False
|
||||
self._pipes_connected = False
|
||||
|
||||
if stdin == subprocess.PIPE:
|
||||
self._pipes[0] = None
|
||||
|
|
@ -213,6 +214,7 @@ async def _connect_pipes(self, waiter):
|
|||
else:
|
||||
if waiter is not None and not waiter.cancelled():
|
||||
waiter.set_result(None)
|
||||
self._pipes_connected = True
|
||||
|
||||
def _call(self, cb, *data):
|
||||
if self._pending_calls is not None:
|
||||
|
|
@ -256,6 +258,15 @@ def _try_finish(self):
|
|||
assert not self._finished
|
||||
if self._returncode is None:
|
||||
return
|
||||
if not self._pipes_connected:
|
||||
# self._pipes_connected can be False if not all pipes were connected
|
||||
# because either the process failed to start or the self._connect_pipes task
|
||||
# got cancelled. In this broken state we consider all pipes disconnected and
|
||||
# to avoid hanging forever in self._wait as otherwise _exit_waiters
|
||||
# would never be woken up, we wake them up here.
|
||||
for waiter in self._exit_waiters:
|
||||
if not waiter.cancelled():
|
||||
waiter.set_result(self._returncode)
|
||||
if all(p is not None and p.disconnected
|
||||
for p in self._pipes.values()):
|
||||
self._finished = True
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue