Skip to content

Commit 12cd899

Browse files
fix subprocess cancellation
1 parent d17f28f commit 12cd899

File tree

1 file changed

+12
-0
lines changed

1 file changed

+12
-0
lines changed

Lib/asyncio/base_subprocess.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def __init__(self, loop, protocol, args, shell,
2626
self._pending_calls = collections.deque()
2727
self._pipes = {}
2828
self._finished = False
29+
self._pipes_connected = False
2930

3031
if stdin == subprocess.PIPE:
3132
self._pipes[0] = None
@@ -213,6 +214,7 @@ async def _connect_pipes(self, waiter):
213214
else:
214215
if waiter is not None and not waiter.cancelled():
215216
waiter.set_result(None)
217+
self._pipes_connected = True
216218

217219
def _call(self, cb, *data):
218220
if self._pending_calls is not None:
@@ -256,6 +258,16 @@ def _try_finish(self):
256258
assert not self._finished
257259
if self._returncode is None:
258260
return
261+
if not self._pipes_connected:
262+
# self._pipes_connected can be False if not all pipes were connected
263+
# because either the process failed to start or the self._connect_pipes task
264+
# got cancelled. In this broken state we consider all pipes disconnected and
265+
# to avoid hanging forever in self._wait as otherwise _exit_waiters
266+
# would never be woken up, we wake them up here.
267+
self._finished = True
268+
for waiter in self._exit_waiters:
269+
if not waiter.cancelled():
270+
waiter.set_result(self._returncode)
259271
if all(p is not None and p.disconnected
260272
for p in self._pipes.values()):
261273
self._finished = True

0 commit comments

Comments
 (0)