mirror of
https://github.com/python/cpython.git
synced 2025-11-25 04:34:37 +00:00
[3.14] gh-103847: fix cancellation safety of asyncio.create_subprocess_exec (GH-140805) (#141446)
gh-103847: fix cancellation safety of `asyncio.create_subprocess_exec` (GH-140805)
(cherry picked from commit ef474cfafb)
Co-authored-by: Kumar Aditya <kumaraditya@python.org>
This commit is contained in:
parent
42e0468209
commit
7e9400c3e6
3 changed files with 51 additions and 1 deletions
|
|
@ -26,6 +26,7 @@ class BaseSubprocessTransport(transports.SubprocessTransport):
|
|||
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 @@ class BaseSubprocessTransport(transports.SubprocessTransport):
|
|||
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 @@ class BaseSubprocessTransport(transports.SubprocessTransport):
|
|||
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