@@ -26,7 +26,6 @@ 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
3029
3130 if stdin == subprocess .PIPE :
3231 self ._pipes [0 ] = None
@@ -214,7 +213,6 @@ async def _connect_pipes(self, waiter):
214213 else :
215214 if waiter is not None and not waiter .cancelled ():
216215 waiter .set_result (None )
217- self ._pipes_connected = True
218216
219217 def _call (self , cb , * data ):
220218 if self ._pending_calls is not None :
@@ -235,6 +233,7 @@ def _process_exited(self, returncode):
235233 if self ._loop .get_debug ():
236234 logger .info ('%r exited with return code %r' , self , returncode )
237235 self ._returncode = returncode
236+
238237 if self ._proc .returncode is None :
239238 # asyncio uses a child watcher: copy the status into the Popen
240239 # object. On Python 3.6, it is required to avoid a ResourceWarning.
@@ -243,6 +242,13 @@ def _process_exited(self, returncode):
243242
244243 self ._try_finish ()
245244
245+ # gh-119710: Wake up futures waiting for wait() as soon as the process
246+ # exits.
247+ for waiter in self ._exit_waiters :
248+ if not waiter .done ():
249+ waiter .set_result (returncode )
250+ self ._exit_waiters = None
251+
246252 async def _wait (self ):
247253 """Wait until the process exit and return the process return code.
248254
@@ -258,15 +264,7 @@ def _try_finish(self):
258264 assert not self ._finished
259265 if self ._returncode is None :
260266 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- for waiter in self ._exit_waiters :
268- if not waiter .done ():
269- waiter .set_result (self ._returncode )
267+
270268 if all (p is not None and p .disconnected
271269 for p in self ._pipes .values ()):
272270 self ._finished = True
@@ -276,11 +274,6 @@ def _call_connection_lost(self, exc):
276274 try :
277275 self ._protocol .connection_lost (exc )
278276 finally :
279- # wake up futures waiting for wait()
280- for waiter in self ._exit_waiters :
281- if not waiter .done ():
282- waiter .set_result (self ._returncode )
283- self ._exit_waiters = None
284277 self ._loop = None
285278 self ._proc = None
286279 self ._protocol = None
0 commit comments